ವಿಕಿಪೀಡಿಯ tcywiki https://tcy.wikipedia.org/wiki/%E0%B2%AE%E0%B3%81%E0%B2%96%E0%B3%8D%E0%B2%AF_%E0%B2%AA%E0%B3%81%E0%B2%9F MediaWiki 1.47.0-wmf.2 first-letter ಮಾದ್ಯಮೊ ವಿಸೇಸೊ ಪಾತೆರ ಬಳಕೆದಾರೆ ಬಳಕೆದಾರೆ ಪಾತೆರ ವಿಕಿಪೀಡಿಯ ವಿಕಿಪೀಡಿಯ ಪಾತೆರ ಫೈಲ್ ಫೈಲ್ ಪಾತೆರ ಮಾದ್ಯಮೊವಿಕಿ ಮಾದ್ಯಮೊವಿಕಿ ಪಾತೆರ ಟೆಂಪ್ಲೇಟ್ ಟೆಂಪ್ಲೇಟ್ ಪಾತೆರ ಸಕಾಯೊ ಸಕಾಯೊ ಪಾತೆರ ವರ್ಗೊ ವರ್ಗೊ ಪಾತೆರ ತಡ್ಯ ತಡ್ಯ ಪಾತೆರ ಕರಡು ಕರಡು ಪಾತೆರ TimedText TimedText talk ಮೋಡ್ಯೂಲ್ ಮೋಡ್ಯೂಲ್ ಪಾತೆರ Event Event talk ಆಟಿ 0 3631 360715 359553 2026-05-16T07:18:08Z ChiK 1136 removed [[Category:ತುಲು ತಿಂಗೊಲು]]; added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360715 wikitext text/x-wiki '''ಆಟಿ''' ತುಲುವೆರೆನ ೧೨ ತಿಂಗೊಲುಲೆಡ್ ಒಂಜಿ. ತುಲುಟು ಉಂದು ನಾಲನೆ ತಿಂಗೊಲು. [[ಪಗ್ಗು]], [[ಬೇಸ]], ಕಾರ್ತೆಲ್, ಆಟಿ, [[ಸೋಣೊ|ಸೋನೊ]], [[ನಿರ್ನಾಲೊ]], [[ಬೊಂತ್ಯೊಲು|ಬೊಂತೆಲ್]], [[ಜಾರ್ತೆ]], ಪೆರಾರ್ತೆ, [[ಪೊನ್ನಿ]], [[ಮಾಯಿ]], [[ಸುಗ್ಗಿ]]. ಇಂಚ ತುಳುಟು ಪದ್ರಾಡ್ ತಿಂಗೊಳುಲು ಉಂಡು.<ref>http://www.suddi9.com/?p=36729</ref> ತುಳುವೆರೆಗ್ ಬಿಸುಡ್ದು ಬುಕ್ಕೊ ಪೊಸ ಒರ್ಸ ಸುರು ಆಪುಂಡು. ಪಗ್ಗುದ ದೊಂಬು, ಬೇಸ್ಯದ ಬೆಪ್ಪು, ಕಾರ್ತ್ಯೊಲುದ ಬರ್ಸನ್ ಮುಗಿತ್‌ದ್ ಕಾರ್ ದೀಪುನ ತಿಂಗೊಲು ಬರ್ಸ ದೊಂಬುದ ಬೆರಕೆಡ್ ಬತ್ತಿ, ಸೀಕ್ ಸಂಕಟೊಲೆಗ್ ಜನೊಕುಲು ತನ್ಕುಲೆ ಸರ‍್ರೊನು ಒಡ್ಡೊನುನ ತಿಂಗೊಲು. ಅವ್ವೇ ಆಟಿ. [[ತುಳು ಬಾಸೆ|ತುಳು]]ವ ಕಾಲಕೊಂದೆಡ್ ತೂಂಡ ತೆರಿಯು ಆಟಿಡ್ ಒಂಜಿ ರಡ್ಡ್ ದಿನ ಜಾಸ್ತಿಯೇ ಉಪ್ಪುಂಡು. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ |- | ೦೪ || ಆಟಿ || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || [[ಮಕರ ಸಂಕ್ರಾಂತಿ]] |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]],[[ಶಿವರಾತ್ರಿ]] |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]],[[ಕೆಡ್ಡೆಸ]] |} == ನಂಬುಗೆ == == ಆಚರಣೆ == # [[ಆಟಿಕಳೆಂಜ]] # ಆಟಿ ಕುಲ್ಲುನಿ # ಆಟಿದ ಅಗೆಲ್ ಬಲಸುನಿ # ಆಟಿ ಅಡ್ಪುನಿ( ಆಟಿ ಪಿದಾಯಿ ಪಾಡುನಿ) # ಆಟಿದ ಮರ್ದ್ # ಆಟಿಡ್ ದಾನ ಬುಡ್ಪು ಕಿರಮ # ಆಟಿದ ಗೊಬ್ಬು == ಆಟಿದ ಮರ್ದ್ == [[File:Hale Tree Medicin preparation.JPG|thumb|ಪಾಲೆದ ಕೆತ್ತೆನ್ ಕಡೆದ್ ದೆತ್ತ್‌ನ ರಸೊ]] ಆಟಿ ಅಮಾಸೆದ ದುಂಬುನಾನಿ ಪೊರ್ತು ಕಂತ್‌ನೆಡ್ದ್ ಬುಕ್ಕೊ ಪಾಲೆದ ಮರತಡಿಕ್ಕ್ ಪೋದು ‘ಎಲ್ಲೆ ಮರ್ದ್ ಕೊನೊಯೆರೆ ಬರ್ಪೆ. ನಿನ್ನ ಪೇರ್‌ಡ್ ಮರ್ದಾಯಿ ಮರ್ದ್ ದಿಂಜಾದ್ ದೀಲ’ ಪಂದ್ ಮರತ ಮುದೆಲ್‌ಡ್ ಬೊಲ್ಲು ಕಲ್ಲ್ ದೀದ್ ಬತ್ತ್, ಪುಲ್ಯ ಕಾಂಡೆ ಇಲ್ಲದಕುಲು ಲಕ್ಕೆರೆ ದುಂಬು [[ಕಲ್ಲ್]] ದೀದ್ ಬತ್ತಿ ಆಂಜೊವು ಬತ್ತಲೆ ಪೋದು ದುಂಬುನಾನಿ ಗುರ್ತಗಾದ್ ದೀನ ಕಲ್ಲ್‌ಡ್ ಗುದ್ದ್‌ದ್ ಮರತ ಕೆತ್ತೆ ಕನಪೆರ್. [[ಮರ]]ಕ್ಕ್ ಕರ್ಬ ತಾಗಾಯೆರೆ ಬಲ್ಲಿ ಪನ್ಪಿ ನಂಬುಗೆಗಾತ್ರ ಕಲ್ಲ್ ಡ್ ಗುದ್ದುವೆರ್. ಕೆಲವು ಕೋಡಿಡ್ ಕೂಲಿಡ್ ತುಚ್ಚಿದ್ ಪೇರ್ ಕೆತ್ತೆ ಕನಪುನವುಲ ಉಂಡು. ಮರ್ದ್ ಕನಯೆರೆ ಪೋನಗ ಮೈಟ್ ಕುಂಟು ಇತ್ತ್ಂಡ ಮರ್ದ್ ಆಜುಂಡು ಅತ್ತಂದೆ ಮರಟ್ ಉಪ್ಪುನ ಕುಲೆ, ಪಿಸಾಸಿಲು ತೊಂದರೆ ಕೊರ್ಪ ಪನ್ಪಿನವು ನಂಬಿಕೆಲಾ ಅಂದ್, ಪೋಡಿಗೆಲಾ ಅಂದ್. ಪೇರ್ ಕೊರ್ಪಿನ ಮರಕ್ಕ್‌ಲ್ ಪಕ್ಕಿದ ಸೊರ ಲಕ್ಕುನ, ನೇಸರ್ ಉದಿಪುಗು ದುಂಬುದ ಪೊರ್ತು ಜಾಸ್ತಿ ಪೇರ್ ಕೊರ್ಪುಂಡು. ಬುಕ್ಕೊ ಅಯಿತ್ತ ಪೇರ್ ಆಜುಂಡು ಪಂದ್ ತೆರಿದ್ ಇತ್ತಿ ಹಿರಿಯಕುಲು ಪುಲ್ಯ ಕಾಂಡೆ ನೇಸರುದಿಪೆರೆ ದುಂಬು ಪಾಲೆದ ಪೇರ್ ಕನಯೆರೆ ಪೋವೊಂದಿತ್ತೆರ್. ಆಂಜೋವು ಕನತಿ ಪಾಲೆದ ಕೆತ್ತೆಗ್ ಇಲ್ಲದ ಪೊಂಜೊವು ಎಡ್ಡೆ ಮುಂಚಿ, ಓಮ, ಶುಂಟಿ, ಬೊಳ್ಳುಳ್ಳಿ, ಜೀರಿಗೆ ಪಾಡ್ದ್ ಕಡೆದ್ ರಸ ಗೆತ್ತ್, ಅಯಿಕ್ಕ್ ತೊಡ್ಡೆದ ನೈ ಪಾಡ್ದ್ ಬೆರೆಪುವೆರ್. ಅಯಿಟಿತ್ತಿ ನಂಜಿನ್ ಗೆಪ್ಪೆರೆ ಬೊಲ್ಲು ಕಲ್ಲ್ ಅತಂಡ ಕರ್ಬದ ತುಂಡು ಕಾಯಿತ್‌ದ್ ಪಾಡ್ದ್ ನೇಸರ್ ಮೂಡಿಯೆರೆ ದುಂಬೆ ಮಾತೆರೆಗ್ಲಾ ಬಜಿ ಬಂಜಿಗ್ ಪರ್ಯರೆ ಕೊರ್ಪೆರ್. ಪಾಲೆದ ಪೇರ್‌ದ ಕೈಪೆಗ್ ಓಲೆ ಬೆಲ್ಲದ ಚೀಪೆ ಮಲ್ಪುವೆರ್. ಮರ್ದ್ ಪರ್ದಾಯಿನ್ನೇ ಮೆತ್ತೆದ ಅತ್ತಂಡ ತಾರಾಯಿದ ಗಂಜಿ ಮಲ್ತ್ ಉನ್ಯರೆ ಕೊರ್ಪೆರ್. ಈ ಮರ್ದ್ ಪರ್‌ಂಡ ಒರ್ಸೊ ಇಡೀ ಸೀಕ್ ಬರ್ಪುಜಿ ಪಂಡ್‍ದ್ ಪೆರಿಯಕುಲೆನ ನಂಬುಗೆ. == ಆಟಿಡ್ ದಾನ ಬುಡ್ಪುನ ಕ್ರಮೊ == ಆಟಿಡ್ ಬಾಕಿ ದಿನೊರದುಲಾ ಜಾಸ್ತಿ ಇಸೇಸ ಇತ್ತಿನ ದಿನ ಆಟಿ ಅಮಾಸೆ. ಆನಿ [[ಕಾಂಡೆ]] ತೋಡು ಅತಂಡ ಸುಧೆಟ್ ಮೀದ್ [[ಬಾರೆ]]ದ ಕೊಡಿ ಇರೆಟ್ ನವದಾನ್ಯ, ಪಂಚ ಪುಷ್ಪಲಾಯಿನ ತೇರ್ ಪುರ್ಪ, ನಂಜಿ [[ಬಟ್ಟಲ್]], ಸಂಕಪುಷ್ಪ, [[ತಾಮರೆ|ತಾವರೆ]] ಪೂ, [[ಬೇಲಿ]] ದಾಸನ್, ತರೆಯಿನ ಪಣವು, [[ಬಚ್ಚಿರೆ]] [[ಬಜ್ಜೆಯಿ]] ದೀದ್, ಇರೆತ್ತ ಕೊಡಿಟ್ ನಿನೆ ಪೊತ್ತಾದ್ ದೀದ್ [[ನೀರ್|ನೀರ್‌]]ಡ್ ದಾನ ಬುಡ್ಪೆರ್. ಅವೆನ್ ಪಕ್ಕಿ ಪಾರಣೆಲ್ ತಿಂದ್ ಬಂಜಿ ದಿಂಜದ್ ಪೋವಡ್ ಪಂದ್ ಪೆರಿಯಕುಲೆನ ನಂಬುಗೆ. ಆನಿ ಪಾಲೆದ ಮರಟ್ಟ್ ಬೂಮಿದೇವಿ ತನ್ನುಡಲ್‌ಡ್ ಇತ್ತಿ ಸರ್ವ ಮರ್ದ್‌ದ ಸತ್ವೊನುಲಾ ಅಯಿಟ್ಟ್ ದಿಂಜದುಪ್ಪುವಲ್ ಪನ್ಪಿ ನಂಬಿಕೆ ತುಳುವ ಹಿರಿಯೆರೆನವು. == ಆಟಿ ಕುಲ್ಲುನ == ಪುಣಿದಾಂತಿ ಕಂಡತ್ತ್, ತಮೆರಿಜ್ಜಂದಿ ಪೊಣ್ಣತ್ತ್, ಮನಸ್‌ದಾಂತಿ ಒನಸತ್ತ್ ಪನ್ಪಿ ಗಾದೆದಂಚ ಮದಿಮೆ ಆಯಿ ಪೊಣ್ಣು ಜೀವೊಗು ತಮೆರಿ ಏತ್ ತಲ್ಮೆನ ಕೊರ್ಪುಂಡು ಪನ್ಪುನೆನ್ ತೆರಿಯೊಡಾಂಡ ಆಟಿ ಬರೊಡು. ಆಟಿಡ್ ಬೇಲೆಲೆಗ್ ಒಂತೆ ಪುರ್ಸೊತುಪ್ಪುನೆಡ್ ಮದಿಮೆ ಆದ್ ಬತ್ತಿ ಪೊಣ್ಣನ್ [[ಅಪ್ಪೆ]] ಇಲ್ಲಗ್ ಕಡಪುಡುನು ವಾಡಿಕೆ. [[ಮಾಮಿ]] ಇಲ್ಲದ ಬೆಪ್ಪು ಮಗಲೆಗ್ ಮುಟ್ಟೆರೆ ಬಲ್ಲಿ. ಅಂಚನೆ ಬೆನ್ನಿದ ಬೇಲೆಲೆಗ್ ಪುರ್ಸೊತು ಇಪ್ಪುನಗ ಇಲ್ಲಡ್ ಮಗಲಿತ್ತ್ಂಡ ಕುಸಿ ಇಪ್ಪುಂಡು, ಆಲೆನ ಬೇನೆ ಬೇಸರ್, ಕುಸಿ, ಕೊಂಡಾಟ ತೆರಿಯೊನೊಲಿ ಪನ್ಪಿ ಉದ್ದೇಸೊಡು ಅತ್ತಂದೆ ಆಟಿಡ್ ಪೊಣ್ಣು ಬಂಜಿನಾಲ್ ಆಂಡ ಗರ್ಬೊಗು ಕುಲೆತ್ತ ಚಾಯೆ ಬೂರುಂಡು, ಅತ್ತಂದೆ ನಟ್ಟ ಅರೆಗಾಲೊಡು ಪೆದುವೆರ್ ಪನ್ಪಿನ ನಂಬುಗೆ ಉಂಡು. ಆ ಪೊರ್ತುಡು ಜೋಕುಲೆಗ್ ಬುಕ್ಕೊ ಪೆದ್ಮೆದಿಗ್ ಬಙ ಆಪುಂಡು ಪಂದ್ ಪೊಸತಾದ್ ಮದಿಮೆ ಆಯಿನ ಪೊಣ್ಣನ್ ತಮೆರಿಗ್ ಲೆತೊ ಬರ್ಪುನ ಕೆರಮ್ಮೊ ತುಳುವೆರೆಡ ಉಂಡು. ಈ ಕ್ರಮೊಕ್ಕು ಆಟಿ ಕುಲ್ಲುನು ಪಂದೇ ಪನ್ಪೆರ್. == ಆಟಿಡ್ ನೇಜಿ ಕಂಡೊದ ದೃಷ್ಟಿ ದೆಪ್ಪುನ ಕಿರಮ == ಕಂಡಡುಪ್ಪುನ ನೇಜಿಗ್ ದೃಷ್ಟಿ ಆಯೆರೆ ಬಲ್ಲಿ, ಕಂಡೊದ ನಂಜಿ ಪೋವೊಡು ಪಂದ್ ಆಟಿ ಅಮಾಸೆದಾನಿ [[ಕಾಯೆರ್‌]]ದ ಕನೆ ಅತಂಡ ಗೆಲ್ಲ್ ಕುತ್ವೆರ್. ಮೂಜಿ ಕಬರ್‌ದ [[ಕೋಲು]]ಗು ಕಾಪು ಪಂತಿ, [[ಬೈ]] ಕಟ್ಟ್‌ದ್ ಮಿತ್ತ್ [[ಬೆದ್‍ರ್|ಬೆದ್‌ರ್‌]]ದ ಅಂಡೆಡ್ [[ಕಳ್ಳಿ]] ನಡ್ಪೆರ್. ಅಯಿಕ್ಕ್ ಕಳ್ಳಿ ಕಾಪು ಮಲ್ಪುನು ಪನ್ಪೆರ್. == ಆಟಿ ಕಳೆಂಜ == [[File:Aati kalenja 01.jpg|thumb|ಆಟಿ ಕಳೆಂಜ]] [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿ ಕಳೆಂಜೆ]] ತುಳುನಾಡ ಆಟಿದ ಇಸೇಸ ಆರಾಧನೆ ಬುಕ್ಕೊ ಆಕರ್ಷಣೆ. ಕಳೆಂಜೆ ಆಟಿದ ಮಾರಿನ್ ಗಿಡರೆರೆ ಇಲ್ಲಿಲ್ಲಗ್ ಬತ್ತ್ ನಲಿತ್ ಅರಿ ತಾರಾಯಿ ಕಾಣಿಗೆ ಪಡೆದ್ ಪೋಂಡ ಇಲ್ಲಡ್ ಪೊಲಿ ಉರ್ಕರುಂಡು ಪನ್ಪಿ ನಂಬಿಕೆ ನಮ್ಮವು. ಆಟಿಡ್ ಪೊಣ್ಣು ಬಾಲೆ ಮದಿಮಾಲಾಂಡ ಅನಿಷ್ಠ ಪನ್ಪಿ ನಂಬೊಲಿಗೆ ಕೆಲವು ಕಡೆಟಿತ್ತ್‌ದ್, ಆಟಿಡ್ ಮದಿಮಲಾಯಿನ ಪೊಣ್ಣಗ್, ಸೀಕ್‌ದ ಜೋಕುಲೆಗ್, ಗೊಡ್ಡು ಪೆತ್ತಗ್, ಫಲಕೊರಂದಿ ತಾರೆಗ್ ಬುಕ್ಕೊ ಸಂತತಿ ಆವಂದಿ ಪೊಂಜೋವುಲೆಗ್ ಆಟಿ ಕಳೆಂಜಡ ತರೆಕ್ಕ್ ನೀರ್ ಮೈಪದ್ ಕಳೆಂಜಗ್ ದಾನೊ ಕೊರ್‌ಂಡ ಆ ಅನಿಷ್ಠ ಕಳೆಯುಂಡು, ಜೋಕುಲಾಪುಂಡು ಫಲ ದಿಂಜಿದ್ ಉರ್ಕರುಂಡು ಪನ್ಪಿ ನಂಬಿಕೆಲ ತುಳುನಾಡ್‌ಡ್ ಉಂಡು.<br> ತಿರಿ ಕಟ್ಟೊಂದು, ಅರದಲ ಪೂಜಿದ್, ಪನೊಲಿದ ತತ್ರ ಪತೊಂದು ಸಂಧಿ ಪನ್ಪಿ ಪೊಂಜೋವುನೊಟ್ಟುಗು ಬರ್ಪಿ ಕಳೆಂಜೆ ನಮ್ಮ ಇಲ್ಲದ ಮಾರಿ ಗಿಡರುವೆ ಪನ್ಪಿ ನಂಬಿಕೆಡ್ದ್‌ಲ ಮೂಲು ನೆಗಪುನು ಮರಿಯಲಡ್ ಬೆನ್ನಿ ಸಾಗೊಲಿದ ಪುರ್ಸೊತುಡು ಉನೆರೆ ಇಜ್ಜಂದೆ ಇಪ್ಪುನಗ ಇತ್ತಿನಕ್ಲ್ ದಾನ ಮಲ್ತೆರ್‌ಂಡ [[ಇಲ್ಲ್]] ಕರಿಯು ಪಂದ್ ತಿರಿ ಕಟ್ಟ್‌ದ್ ಕಲೆಕ್ಕಾದೆ ಜೀವನ ದೀತಿ ಜನಾಂಗ ಬುಕ್ಕೊ ಬೆನ್ನಿದ ಬೇಲೆನೇ ನಂಬಿ ಬೂಮಿಪುತ್ರೆರ್. ಮಾರಿ ಪೋವಡ್ ಪಂದ್ ಪಂಡಲ ಕಾರಣ ಅವ್ವತ್ತ್ ಆಯನ ಇಲ್ಲಗ್ ಇಪ್ಪುನ ತೊಂದರೆಲ್ ಪಂದ್ ತೆರಿಯೊಂದು ಅರಿ ಬಾರ್ ದಾನೊ ಮಲ್ತ್ ಪಾಪದಾಯಗ್‌ಲ ಆಟಿದ ಬಙ ಆಯೆರೆ ಬಲ್ಲಿ ಪನ್ಪಿ ತುಳುವೆರೆನ ಸಂಪ್ರದಾಯ ನೆಗತ್ ತೋಜುಂಡು. == ಆಟಿ ಪಿದಾಯಿ ಪಾಡುನಿ == ಈ ತಿಂಗೊಲುಡು ಇಲ್ಲ್, ಅಟ್ಟೊ ಅಟ್ಟ ಅಡಿತ್ದ್ ಕಜವು ಪಿದಾಯಿ ಪಾಡುನೆ ಕ್ರಮೊ. ಆಟಿ ಪಿದಯಿ ಪಾಡುನು ತುಳುನಾಡ್‌ದ ಇಸೇಸ ಆಚರಣೆ. ಅಟ್ಟೊಡಿತ್ತಿ ಅರಿತ ಮುಡಿ ಕಾಲಿ ಆದ್ ಅಟ್ಟೊ ಅಡಿಪುನ ತಿಂಗೊಲು ಆಟಿ. ದಾಯೆ ಪಂಡ ಬಾಕಿ ತಿಂಗೊಲುಡು ದಿಂಜಿದುಪ್ಪುನ ಅಟ್ಟ, ಕದಿಕೆಲ್ ಕಾಲಿ ಆದಿಪ್ಪುನೆಡ್, ಅಟ್ಟಡಿತ್ತಿ ಬಿತ್ತ್‌ದ ಮುಡಿಲಾ ಬಿತ್ತ್‌ದ್ ಆದಿಪ್ಪುನೆಡ್ದಾದ್ ಮಾಯಿಪು ಪಾಡ್ದ್ ಕಜವು ದೆಪ್ಪೆರೆ ಸುಲಬ ಆಪುಂಡು. ಅಯಿನ್ ಮಾತ ಅಡಿತ್ತ್ ಪಿದಾಯಿ ಪಾಡ್ದ್ ಸೊಚ್ಚ ಮಲ್ಪುನ ಬೇಲೆ ಪೊಂಜೋವುಲೆಗ್ ಉಪ್ಪುಂಡು. ಈ ಕಜವು ಪಿದಾಯಿ ಪಾಡುನ ಕ್ರಮೊಕ್ಕು ಆಟಿ ಪಿದಾಯಿ ಪಾಡುನು ಪಂದ್ ಪನ್ಪೆರ್. ಇತ್ತೆ ಅಟ್ಟದಾಂತಿ ಇಲ್ಲ್, ಪುಗೆದಾಂತಿ ಅಟಿಲ್ ಆಯಿನೆರ್ದಾರ ಆಟಿ ಪಿದಾಯಿ ಪಾಡುನ ಕಿರಮ ತೋಜೊಂದು ಇಜ್ಜಿ. == ಆಟಿಡ್ ಅಗೆಲ್ ಬಲಸುನಿ == ಆಟಿಡ್ ಊರುಡು ಬಡಪತ್ತ್ ಪಂದ್ [[ಬರ್ಸೊ|ಬರ್ಸ]] ದೊಂಬುರ್ದಾವರ ದೈವೊಲೆಗ್ [[ಪೂ]] ನೀರ್ ದೀಯರಾವಂದೆ, ನೇಮ ಕೋಲ ಕೊರ್ರೆ ಆಪುಜಿ. ಅಂಚಾದ್ ಆಟಿ ಕಳೆಂಜೆ ತುಳುನಾಡ್‌ಗ್ ಜಪ್ಪುನಗ ಸಾರತ್ತೊಂಜೆಡ್ [[ಕಲ್ಲುರ್ಟಿ]] ಅಪ್ಪೆ [[ಗುಳಿಗ]] ದೈವೊನ್ ಬುಡ್ದ್ ಒಂಜಿ ಕಮ್ಮಿ ಸಾರ ದೈವೊಲು ಮಲೆ ಏರುವೆರ್ ಪಂದ್ ಸಾನ ಮಾಡೊಲೆಗ್ ಬಾಕಿಲ್ ಪಾಡುನ ಕ್ರಮಲಾ [[ತುಳುನಾಡ್|ತುಳುನಾಡ್‌]]ಡ್ ಉಂಡು. ಕಲ್ಲುರ್ಟಿ, ಗುಳಿಗಗ್, ಕರಿದ್ ಪೋಯಿನಕ್ಲೆಗ್ [[ಅಗೆಲ್]] ತಮ್ಮನ ಬಲಸುವೆರ್. ತೀರ್ ಪೋಯಿನಕ್ಲೆನ್ ೧೬ ಗ್ ಸೇರಾವುನ(೧೬ ಅಗೆಲ್) ಪರಿಪಾಡ್‌ಲ ಆಟಿಡ್ ಉಂಡು. ಆಟಿಡ್ ಕುಲೆಕ್ಕ್‌ಲೆಗ್ ಮದ್ಮೆ ಮಲ್ಪುನ ಇಸೇಸ ಆಚರಣೆ ತುಳುನಾಡ್‌ಡ್ ಇತ್ತ್‌ದ್ ಮದಿಮೆ ಆವಂದೆ ಕರಿದ್ ಪೋಯಿನ ಆಣ್ ಪೊಣ್ಣು ಕುಲೆಕ್ಕ್ ಸಂಬಂದ ತೂದು ಮದಿಮೆ ಮಲ್ಪುವೆರ್. ಅಗೆಲ್ ತಮ್ಮನ ಬಲಸುವೆರ್. == ಆಟಿದ ಗೊಬ್ಬು == {{Main|ಚೆನ್ನೆಮಣೆ}} [[File:Chennemane.jpg|thumb|ಚೆನ್ನೆಮಣೆ]] ದುಂಬುದ ಕಾಲೊಡ್ ಆಟಿದ ಸಮಯೊಡ್ ಪೊರ್ತು ಕಳೆಯೆರೆ ಚೆನ್ನೆ ಗೊಬ್ಬುಂದಿತ್ತೆರ್. ಅಯಿಟ್ಟ್ [[ಕಂಡನಿ]] [[ಬೊಡೆದಿ]], ತಗೆ [[ತಂಗಡಿ]], ಅಮರು ಜೋಕುಲು ಗೊಬ್ಬೆರೆ ಬಲ್ಲಿ ಪನ್ಪಿನ ನಂಬೊಲಿಗೆ ಉಂಡು. ಅಯಿಕ್ಕ್ ಇಂಬು ಕೊರ್ಪುನ ಕೆಲವು ಕತೆಕ್ಕ್‌ಲಾ ಉಂಡು. ಆಟಿದ ಬೇಸರ್ಪು ಕರಿಪೆರೆ ಚೆನ್ನೆ ಗೊಬ್ಬೆರೆ ಕುಲ್ಲಿನ ಕತೆ ದುಂಬರಿದ್ ಲಡಾಯಿಗ್ ತಿರ್ಗುಂಡು. ಕಡೆಕ್ಕ್ ಮಣೆಟ್ಟೇ ಹಾಕೊಂದು ಒರಿ ಸೈಪುನಾಡೆ ಮುಟ್ಟ ಎತ್ತುಂಡು ಪನ್ಪಿನೆಕ್ [[ಅಬ್ಬಯ ದಾರಯ|ಅಬ್ಬಗ ದಾರಗ]]ನ ಕತೆ ಉಂಡು. ಬಾಲೆಜೇವು ಮಾಣಿಗೊ ಪಾಡ್ದನಡ್, ಚೆನ್ನೆಗೊಬ್ಬುಡು ಸೋಲು ನಿಘಂಟ್ ಆನಗ ಬೊಡೆದಿನ್ ಪೇರ್ ಕನಯೆರೆ ಕಡಪುಡ್ದ್ ಮಣೆ ತಿರ್ಗದ್ ದೀನೆನ್ ಅಯಿನ್ನ್ ತೆರಿನ ಮಾನಿಗೊ ದತ್ತ ಕಾರ್‌ಡ್ ಚೆನ್ನೆಮಣೆ ದೊಂಕ್‌ದ್ ಬಲ್ಲಾಲ್ರೆ ಮೋಸೊಗು ಸಡಿಪುವಲ್. ಅಯಿನ್ನ್ ತಡೆವಂದಿ ಬಲ್ಲಾಲ್ರ್ “[[ಚೆನ್ನೆಮಣೆ|ಚೆನ್ನೆ ಮಣೆ]] ದೊಂಕಿನ ಪೊಣ್ಣು ಈ ಎನ್ನ ಬೂಡು ಒರಿಪವನಾ?” ಪಂದ್ ಹಾಕುವೆರ್. ಆ ಕಾಲೊಡು ಚೆನ್ನೆ ಮಣೆಕ್ಕ್ ಆತ್ ಮರ್ಯಾದಿ ಕೊರೊಂದಿತ್ತೆರ್ ಪನ್ಪಿನೆನ್ ಉಂದು ತೆರಿಪಾವುಂಡು. ಬೂಡುದ ಘನತೆ ಗೌರವೊಗ್ ಸಮಾನವಾಯಿನ ಘನತೆ ಚೆನ್ನೆಮಣೆಕ್ಕ್ ಅಂಚನೆ ಮಾನಾದಿಗೆ ಚೆನ್ನೆ ಗೊಬ್ಬುಗು ಇತ್ತ್ಂಡ್. == ಆಟಿದ ಗಾದೆಲು == # ಅಟಿಡ್ ತೆಡಿಲ್‍ ಬತ್ತ್ಂಡ ಆಟ್ಟ ಪೊಲಿಪೋವು, ಸೋಣೊಡು ತೆಡಿಲ್‍ ಬತ್ತ್ಂಡ ಸೊಂಟ ಪೊಲಿಪೋವು. # ಆಟಿಡ್‍ ಕಣೆ ಬತ್ತ್ಂಡ ಆಟ್ಟ ಪೊಲಿಪೋವು, ಸೋಣೊಡು ಕಣೆ ಬತ್ತ್ಂಡ ಸೊಂಟ ಪೊಲಿಪೋವು. # ಆಟಿದ [[ಪೆಲಕಾಯಿ]] ನಂಜಿ ಮಗಾ- ಅಮ್ಮೆ ಬರ್ಪೆನಾ ತೂಲ ಮಗಾ. # ಅಟಿಡ್‍ ಪೊಣ್ಣು ಪುಟ್ಟುನು ಎಚ್ಚಗೆ. # ಆಟಿದ ದೊಂಬು ಆನೆದ ಬೆರಿ ಪುಡಾವು. # ಆಟಿಡ್ ಆನೆದ ಅಡಿಟ್ಟ್ ಬೂರುಂಡಲಾ ಕೆಯಿಕ್ಕ್ ಕೇಡ್ ಇಜ್ಜಿಗೆ. == ಆಟಿದ ತೆನಸುಲು == ದುಂಬುದ ಕಾಲೊಡ್ ಬೇಲೆ ಇಜ್ಜಂದಿನೆಡ್ ಬೆಂದ್ ತಿಂದ್ ಜೀರ್ಣೆ ಮಲ್ಪುನ ಜೀವೊಲೆಗ್ ಅಜೀರ್ಣ ಆಯೆರೆ ಬಲ್ಲಿ ಪಂದ್ ಅರಿ, ರಾಗಿ, ಗೋಧಿತ ತೆನಸ್ ಒಂತೆ ಕಮ್ಮಿ ಮಲ್ತ್ ಬೇಗ ಜೀರ್ಣ ಆಪುನ ತೆನಸ್‌ಲೆನ್ ಅಟ್ಟಿಲ್ ಮಲ್ತ್ ತಿನ್ಪೆರ್. ಅವು ಪಂಡ ನರೆ, [[ಕೇನೆ]], [[ಕಣಿಲೆ]], [[ಚೇವು]], [[ನೀರ್ ಕುಕ್ಕು]], [[ಪೆಲಕಾಯಿದ ಗೂಂಜಿ]], [[ಪೆಲತರಿ]], [[ಕೆರೆಂಗ್]], [[ತಜಂಕ್ ತಪ್ಪು|ತಜಂಕ್]], [[ನುರ್ಗೆ ತೊಪ್ಪು]], [[ಈಯೆರ್‌ದ ಕಾಯಿ]], [[ಲಾಂಬು]], [[ಉಪ್ಪಡ್ ಪಚ್ಚಿಲ್|ಉಪ್ಪಡ್‌ಪಚ್ಚಿಲ್]], [[ಕೇನೆದ ಪುಂಡಿ]], ಮರಚೇವು ಪಂದ್ ಕನತ್‌ದ್ ಕಜಿಪು, ಅಡ್ಯೆ ಮಲ್ಪುನು, ಉದುರಿ ಬೂರುದ ಕಂಡೆ, [[ಅರ್ತಿದ ಕೆತ್ತೆ]], [[ಬೇಂಗದ ಕೆತ್ತೆ]], [[ಇರ್ಪೆದ ಕೆತ್ತೆ]], [[ತಾರಾಯಿ]]ದ, [[ಕೊತ್ತಂಬರಿ]], [[ಮೆತ್ತೆ]], [[ದಾಸಿಮಿ]]ದ [[ಗಂಜಿ]] ಮಲ್ತ್ ತಿನ್ಪುನು ತುಳುವೆರೆಗ್ ಈ ತಿಂಗೊಲುಡು ಅನಿವಾರ್ಯ ಬುಕ್ಕೊ ಅಬ್ಯಾಸಲಾ ಆದ್ ಪೋಪುಂಡು.<br> ಆಟಿ ಅರಂಟ್ ತಿನ್ಪಿ ತಿಂಗೊಳು ಪನ್ಪಿನಂಚ ಬಾಕಿದ ೧೧ ತಿಂಗೊಲು ಬುಡು ಕೈಟ್ ಮಲ್ತೊಂದಿತ್ತಿ ತೆನಸ್ ಕಮ್ಮಿ ಮಲ್ತ್ ಪೊಂಜೋವುಲು ಕಾಡ್ ಬಲ್ಲೆ, ತೋಡು ಕಂಡ ನಾಡೊಂದು ಪೋಪೆರ್. ಸಾರ ಬಗೆತ ಸೀಕ್‌ಗೆ, ಸಾರತ್ತೊಂಜಿ ಬಗೆತ ಮರ್ದ್ಗೆ ಪನ್ಪಿನಂಚ ಅರಿ ಕಮ್ಮಿ ಗಲಸುನ ತೆನಸ್ ಒನಸ್‌ಲ ಆದ್, ಮರ್ದ್ಲ ಆಪುನ ಸಪ್ಪು, ಕಂಡೆ, ಬೇರ್, ನಾರ್ ಕನತ್ [[ಪತ್ರೊಡೆ]], [[ತೇಟ್ಲ]], ಗಂಜಿ, [[ಕಷಾಯ|ಕಸಾಯ]], ಅಡ್ಯೆ, ಅಂಬೆಲಿ ಅಡ್‌ದ್ ಬಂಜಿ ಬುಕ್ಕೊ ಆರೋಗ್ಯ ದಿಂಜಾವೊಂದು ಇತ್ತೆರ್. ತಿಮರೆ ಆಟಿಡ್ ಕೈಪೆ ಪಂದ್ ಅಡೊಂದಿಜ್ಜಾಂಡ್. == ಆಟಿ, ಆಟಿ ತಿಂಗೊಲುದ ಬಗೆಟ್ಟ್ ಬುಕ್ಕೊ ತುಳುನಾಡ್ ದ ಆಚರಣೆಲೆದ ಬಗೆಟ್ ಓದೊಡಾಯಿ ಬೂಕುಲು== # ತುಳುನಾಡಿನ ಆಚರಣೆಗಳು- ವಾರ್ಷಿಕ ಆವರ್ತನ ಸಾಂಸ್ಕೃತಿಕ ಆಧ್ಯಯನ, ದಿವಾಕರ್ ಕೆ. (ದಿವ ಕೊಕ್ಕಡ, ೨೦೧೩) # [[ಬೊಳ್ಳಿ]] ಸಂಭ್ರಮೊ-ಸರಣಿ ಉಪನ್ಯಾಸೀ ಮಾಲೆದ ಎಗ್ಗೆಲು-೧-೨೫, ಧರ್ಮಸ್ಥಳ ಮಂಜುನಾಥೇಶ್ವರ ತುಳು ಪೀಠ ಮಂಗಳೂರು ವಿಶ್ವವಿದ್ಯಾನಿಲಯ, ೨೦೨೧ # ಸೇರಿಗೆ, ಕೆ. ಜಿನ್ನಪ್ಪ ಗೌಡ (ಸಂ.), ಮದಿಪು ಪ್ರಕಾಶನ, ಮಂಗಳ ಗಂಗ್ರೋತ್ರಿ, ೨೦೦೦ # ಕರಾವಳಿ ಆಚರಣೆಗಳು, ವಾಮನ ನಂದಾವರ(ಸಂ) ಭಾಗ-೧ & ೨, ಕನ್ನಡ ಮತ್ತು ಸಂಸ್ಕೃತಿ ಇಲಾಖೆ, ಬೆಂಗಳೂರು, ೨೦೧೪ == ಪಿದಾಯಿ ಕೊಂಡಿ == *http://ravirajkateel.blogspot.in/2014/07/blog-post.html == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] [[ವರ್ಗೊ:ತುಳುವೆರೆ ಆಟಿ ತಿಂಗೊಲು]] [[ವರ್ಗೊ:ತುಳು ಸಂಸ್ಕೃತಿ]] [[ವರ್ಗೊ:ತುಳು ಜಾನಪದ]] gwfz2p45a46evj26zt0tw8cy7o6qfc8 ಆಟಿ ಕುಲ್ಲುನು 0 3633 360722 356171 2026-05-16T07:20:25Z ChiK 1136 removed [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360722 wikitext text/x-wiki '''ಆಟಿದ ಕುಲ್ಲುನೆ''' ಸೌರಮಾನೊದ ನಾಲೆನೆ ತಿಂಗೊಲು [[ಆಟಿ]]ಡ್ ಈ ಕ್ರಮ ಆಚರಣೆಡ್ ಉಂಡು. ಉತ್ತರಾಯನೊ ಕರಿದ್ ದಕ್ಷಿಣಾಯನೊದ ಈ ಆಟಿ ತಿಂಗೊಲುಡು ಕೀರಿಕುಟ್ಟ್‌ದ ಬರ್ಪುಂಡು. ಈ ಬರ್ಸೊಗು [[ಭೂಮಿ]] ಪೂರಾ ಪರ್ಂದ್‌ದ್ ಪೋಪುಂಡು. ಆಟಿಡ್ [[ಭೂಮಿ]] ಸೀತೊ ಏರ್ದಿಪ್ಪುಂಡು. ಇಂದೆಕಾತ್ರೊ ಒಂಜಾತ್ ನಿಸೇದೊ, ಆಟಿಕುಲ್ಲುನೆದ ಪುದರ್ಡ್ ಆಟಿಡ್ ಇಸೇಸೊಡ್ ಆಪುಂಡು.<ref>{{Cite web |title=ತುಳುನಾಡಿನ ವಿಶಿಷ್ಟ ಆಚರಣೆ ಆಟಿ ಕಳೆಂಜ |url=https://vijaykarnataka.com/lavalavk/culture/-/articleshow/15235460.cms |access-date=2026-03-26 |website=Vijay Karnataka |language=kn}}</ref> [[ಮದಿಮೆ]] ಆದ್ ಕಂಡನಿಲ್ಲಡೆ ಬತ್ತಿನ ಪೊಣ್ಣು ಸುರುತ ಆಟಿ ತಿಂಗೊಲುನು ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಕರಿಪುನ ಒಂಜಿ ಪಿರಾಕ್‌ದ ಸಂಪ್ರದಾಯ ಉಂದೆನ್ '''ಆಟಿ ಕುಲ್ಲುನು''' ಪಂಡ್‍ದ್ ಲೆಪ್ಪುವೆರ್.<ref>{{Cite web |last=ವಿಕ ಸುದ್ದಿಲೋಕ |title=ತುಳು ಚಾವಡಿ-ಪೊಸ ಮದಿಮಾಲ್ ಆಟಿ ಕುಲ್ಲುನು ದಾಯೆ? |url=http://vijaykarnataka.indiatimes.com/home/languages/tulu/-/articleshow/38811914.cms |archive-url=https://web.archive.org/web/20160322135206/http://vijaykarnataka.indiatimes.com/home/languages/tulu/-/articleshow/38811914.cms |archive-date=2016-03-22 |website=vijaykarnataka.indiatimes.com |language=kn}}</ref> == ಹಿನ್ನೆಲೆ == [[ಆಟಿ]] ತಿಂಗೊಲುಡು ಪೊಸ ಮದಿಮಯ-ಮದಿಮಾಲ್ ಶಾರೀರಿಕವಾದ್ ಒಂಜಾಯೆರೆ ಬಲ್ಲಿ ಪನ್ಪಿನ ನಂಬಿಕೆ. ಅಂಚಾದ್ ಈ ಪೊರ್ತುಡು ಅಕುಲು ಬೇತೆ ಬೇತೆ ಉಪ್ಪೊಡು ಪಂಡ್‌ದ್ ಪೊಣ್ಣನ್ ಅಪ್ಪೆ ಇಲ್ಲಗ್ ಕಡಪುಡುವೆರ್. == ಕಾರಣೊ == ಆಟಿ ಕಷ್ಟದ ತಿಂಗೊಲು. ಅಪಗ ಬೆನ್ನಿದ ಬೇಲೆ ಮುಗಿ ದುಪ್ಪುಂಡು. [[ಕೊಳಕೆ]] ಮಲ್ತಿನಕ್ಲೆನ ಇಲ್ಲಡ್ ಮಾತ್ರ ಅರಿ-ಬಾರ್ ಒರಿದುಪ್ಪುಂಡು. [[ಸುಗ್ಗಿ]] ಮಲ್ತಿನಕ್ಲೆನ ಇಲ್ಲಡ್ ಒಂತೆ ಉಪ್ಪು. ಅವ್ವೇ ಒಂಜೇ ಬುಲೆ ಮಲ್ತಿನಕ್ಲೆನ ಇಲ್ಲಡ್ ಕರಿ ವರ್ಸೊ ಏಣೆಲ್‌ದ ಅರಿ ಪೂರಾ ಕಾಲಿಯಾದುಪ್ಪುಂಡು. ಅಂಚಾದ್ [[ಆಟಿ]]ಡ್ ಕೆರೆಂಗ್, [[ತೇವು]], [[ತಜಂಕ್]], ಮೂಂಡಿ, [[ಉಪ್ಪಡ್ ಪಚ್ಚಿಲ್|ಉಪ್ಪಡಚ್ಚಿಲ್]], [[ಸಾಂತಣಿ]] ಇಂಚಿನ ಸೊತ್ತುಲೆನೇ ತಿಂದ್‌ದ್ ದಿನ ಕರಿಯುವ ಪರಿಸ್ಥಿತಿ. ಈ ಬಂಙನ್ ಪೊಸ ಮದಿಮಲ್ ಅನುಭವಿಸುನ ಬೊಡ್ಚಿ ಪಂಡ್‌ದ್ ಅಪ್ಪೆ ಇಲ್ಲಗ್ ಕಡಪುಡುನ ಕ್ರಮ ಸುರು ಆದುಪ್ಪು. === ಆಟಿ ಕುಲ್ಯರ ಲೆತೊಂದು ಪೋಪುನೆ === ಪೊಸ ಮದಿಮ್ಮಾಲೆ ಸುರತ್ತ ಆಟಿಗ್ ಅಪ್ಪೆ ಇಲ್ಲಡೆಗ್ ಅಪ್ಪೆ ಇಲ್ಲ್ದಕ್ಲ್ ಪೋದು ಲೆತ್ತೊಂದು ಬರ್ಪುನ ಕ್ರಮ. ಮದಿಮ್ಮಾಲೆನ್ ದಾಯೆ ಇಲ್ಲಡೆ ಲೆತೊಂದು ಬರ್ಪುನೆ? ಆಟಿಕುಲ್ಲುನೆಂದ್ ದಾಯೆ ಪನ್ಪೆರ್? ಇಂಚಪೂರ ಪ್ರಶ‍್ನೆಲು ಲಕ್ಕುವೊ. === ಆಟಿಗ್ ಲೆತೊಂದು ಪೋಪುನ ಉದ್ದೇಸೊ === ಆಟಿಡ್ ಸೀಕ್- ಸಂಕಟ ಜಾಸ್ತಿ. ಅಂಚಾದ್ ಪೊಸ ಮದಿಮಲ್ ಈ ಪೊರ್ತುಡು ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಇತ್ತ್‌ಂಡ ಆಲೆಗ್ ಮನಸ್‌ಗ್ ನೆಮ್ಮದಿ ತಿಕ್ಕು. ಅಂಚನೆ ಉಪಚಾರ ಮಲ್ಪೆರೆ ಅಪ್ಪೆಲಾ ತಿಕ್ಕುವೆರ್. ಅಲ್ಪ ಬಂಙ ಇತ್ತ್‌ಂಡಲಾ ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಪೊಣ್ಣು ಕಷ್ಟೊಡುಲಾ ಕುಸಿಡುಪ್ಪುವಲ್. ಮದಿಮೆದ ಸುರುಟೆ ಕಷ್ಟೊದ ಸಮಯೊಡು [[ಮಾಮಿ]] ಇಲ್ಲಡ್ ಇತ್ತಲ್‌ಂಡ ಆಲೆನ ಮನಸ್‌ಗ್ ಮಸ್ತ್ ಬೇಜಾರ್ ಆವು ಪನ್ಪಿನ ಕಾರಣೊಗಾದ್ ಅಪ್ಪೆ ಇಲ್ಲಡೆ ಕಡಪುಡುದು ಕೊರ್ಪಿನ ಸಂಪ್ರದಾಯ ಸುರು ಮಲ್ತ್‌ದುಪ್ಪೆರ್. ಆಟಿದ ದಿರಿಕೂಟ ಬೊಲ್ಲೊಗು, ಜಡಿ ಬರ್ಸೊಗು ಪೊಸ ಮದಿಮಲ್ ಮಾನಸಿಕವಾದ್ ಜಗ್ಗುನ ಬೊಡ್ಚಿ ಪನ್ಪಿನ ಉದ್ದೇಶಲಾ ಉಂದೆತ ಪಿರವುಡುಪ್ಪು. == ಆಟಿ ಸಮ್ಮನೊ == ಆಟಿ ಕುಲ್ಯರ ಬತ್ತ್‌ನ ಮಗಳೆನ್ ಕಂಡಾನಿ ಇಲ್ಲಡೆ ಲೆತೊಂದ್ ಪೋಪುನ ಕ್ರಮೊ ಉಂಡು. ಅಪಗ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡುಂದು ಪನ್ಪೆರ್. ಕಬಿತಡ್ ಇಂಚೊಂಜಿ ಪಾತೆರೊ ಉಂಡು, '''ಬರಾಂದಿ ಬಿನ್ನೆರ್ ಬತ್ತೆರ್ ಮಗ ಸೇಸೊ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡಾಂಡೆ'''. === ಆಟಿದ ನಂಬಿಕೆಲು === ಆಟಿಡ್ ಪೊಣ್ಣು [[ಬಾಲೆ]] [[ಮದಿಮಾಳ್ ಮದಿಮೆ|ಮದಿಮಾಲ್]] ಆಂಡ ಅನಿಷ್ಠ ಪನ್ಪಿ ನಂಬೊಲಿಕೆ ಉಂಡು. ಆಟಿಡ್ ಮದಿಮಲಾಯಿನ ಪೊಣ್ಣಗ್, ಸೀಕ್‌ದ ಜೋಕುಲೆಗ್, ಗೊಡ್ಡು ಪೆತ್ತಗ್, ಫಲಕೊರಂದಿ ತಾರೆಗ್ ಬುಕ್ಕೊ ಸಂತತಿ ಆವಂದಿ ಪೊಂಜೋವುಲೆಗ್ ಆಟಿ ಕಳೆಂಜಡ ತರೆಕ್ಕ್ ನೀರ್ ಮೈಪದ್ ಕಳೆಂಜಗ್ ದಾನೊ ಕೊರ್ಂಡ ಆ ಅನಿಷ್ಠ ಕಳೆಯುಂಡು, ಜೋಕುಲಾಪುಂಡು ಪಲ ದಿಂಜಿದ್ ಉರ್ಕರುಂಡು ಪನ್ಪಿ ನಂಬಿಕೆಲ ತುಳುನಾಡ್‌ಡ್ ಆಟಿಕಳೆಂಜ ಪಾಡ್ದಾನೊಡು ಬರ್ಪುಂಡು. === ಆಟಿದ ಗಾದೆಲು === # ಆಟಿಡ್ ಪೆದ್ದುನ ಬಾಲೆ ಪೊಣ್ಣು # ಆಟಿಡ್ ಕಂಡನಿ ಬುಡೆದಿ ಒಟ್ಟೂಗೆ ಇಪ್ಪರೆ ಆವಂದ್ === ಆಟಿದ ಕತ್ತಲೆ === ಆಟಿದ ಸಮಯೊಡು ಮಿನ್ಪುರಿ ಬರ್ಪುಂಡು. ಕರೆಂಟ್ ಇದ್ಯಾಂದಿ ಇಲ್ಲ್ದ ಸುತ್ತುಡೆ ಮಿನ್ಪರಿದ ಬೊಲ್ಪು ಅಪಾಪಗ ಮಿಂಚುಂಡು. ಅಯಿತ ನಡುಟ್ ಕರ್ಗುಡ ಕತ್ತಲೆ ಬರ್ಪುಂಡು. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ಜಾನಪದ]] [[ವರ್ಗೊ:ತುಳುನಾಡ ಸಂಸ್ಕೃತಿ]] d36t93pyla84q7mkltvu7x2rhaedhrw 360806 360722 2026-05-16T09:32:11Z ChiK 1136 Added {{[[Template:Merge from|Merge from]]}} tag 360806 wikitext text/x-wiki {{Merge from|ಆಟಿಕುಲ್ಲುನೆ|discuss=Talk:ಆಟಿ ಕುಲ್ಲುನು#Proposed merge of ಆಟಿಕುಲ್ಲುನೆ into ಆಟಿ ಕುಲ್ಲುನು|date=ಮೇ ೨೦೨೬}} '''ಆಟಿದ ಕುಲ್ಲುನೆ''' ಸೌರಮಾನೊದ ನಾಲೆನೆ ತಿಂಗೊಲು [[ಆಟಿ]]ಡ್ ಈ ಕ್ರಮ ಆಚರಣೆಡ್ ಉಂಡು. ಉತ್ತರಾಯನೊ ಕರಿದ್ ದಕ್ಷಿಣಾಯನೊದ ಈ ಆಟಿ ತಿಂಗೊಲುಡು ಕೀರಿಕುಟ್ಟ್‌ದ ಬರ್ಪುಂಡು. ಈ ಬರ್ಸೊಗು [[ಭೂಮಿ]] ಪೂರಾ ಪರ್ಂದ್‌ದ್ ಪೋಪುಂಡು. ಆಟಿಡ್ [[ಭೂಮಿ]] ಸೀತೊ ಏರ್ದಿಪ್ಪುಂಡು. ಇಂದೆಕಾತ್ರೊ ಒಂಜಾತ್ ನಿಸೇದೊ, ಆಟಿಕುಲ್ಲುನೆದ ಪುದರ್ಡ್ ಆಟಿಡ್ ಇಸೇಸೊಡ್ ಆಪುಂಡು.<ref>{{Cite web |title=ತುಳುನಾಡಿನ ವಿಶಿಷ್ಟ ಆಚರಣೆ ಆಟಿ ಕಳೆಂಜ |url=https://vijaykarnataka.com/lavalavk/culture/-/articleshow/15235460.cms |access-date=2026-03-26 |website=Vijay Karnataka |language=kn}}</ref> [[ಮದಿಮೆ]] ಆದ್ ಕಂಡನಿಲ್ಲಡೆ ಬತ್ತಿನ ಪೊಣ್ಣು ಸುರುತ ಆಟಿ ತಿಂಗೊಲುನು ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಕರಿಪುನ ಒಂಜಿ ಪಿರಾಕ್‌ದ ಸಂಪ್ರದಾಯ ಉಂದೆನ್ '''ಆಟಿ ಕುಲ್ಲುನು''' ಪಂಡ್‍ದ್ ಲೆಪ್ಪುವೆರ್.<ref>{{Cite web |last=ವಿಕ ಸುದ್ದಿಲೋಕ |title=ತುಳು ಚಾವಡಿ-ಪೊಸ ಮದಿಮಾಲ್ ಆಟಿ ಕುಲ್ಲುನು ದಾಯೆ? |url=http://vijaykarnataka.indiatimes.com/home/languages/tulu/-/articleshow/38811914.cms |archive-url=https://web.archive.org/web/20160322135206/http://vijaykarnataka.indiatimes.com/home/languages/tulu/-/articleshow/38811914.cms |archive-date=2016-03-22 |website=vijaykarnataka.indiatimes.com |language=kn}}</ref> == ಹಿನ್ನೆಲೆ == [[ಆಟಿ]] ತಿಂಗೊಲುಡು ಪೊಸ ಮದಿಮಯ-ಮದಿಮಾಲ್ ಶಾರೀರಿಕವಾದ್ ಒಂಜಾಯೆರೆ ಬಲ್ಲಿ ಪನ್ಪಿನ ನಂಬಿಕೆ. ಅಂಚಾದ್ ಈ ಪೊರ್ತುಡು ಅಕುಲು ಬೇತೆ ಬೇತೆ ಉಪ್ಪೊಡು ಪಂಡ್‌ದ್ ಪೊಣ್ಣನ್ ಅಪ್ಪೆ ಇಲ್ಲಗ್ ಕಡಪುಡುವೆರ್. == ಕಾರಣೊ == ಆಟಿ ಕಷ್ಟದ ತಿಂಗೊಲು. ಅಪಗ ಬೆನ್ನಿದ ಬೇಲೆ ಮುಗಿ ದುಪ್ಪುಂಡು. [[ಕೊಳಕೆ]] ಮಲ್ತಿನಕ್ಲೆನ ಇಲ್ಲಡ್ ಮಾತ್ರ ಅರಿ-ಬಾರ್ ಒರಿದುಪ್ಪುಂಡು. [[ಸುಗ್ಗಿ]] ಮಲ್ತಿನಕ್ಲೆನ ಇಲ್ಲಡ್ ಒಂತೆ ಉಪ್ಪು. ಅವ್ವೇ ಒಂಜೇ ಬುಲೆ ಮಲ್ತಿನಕ್ಲೆನ ಇಲ್ಲಡ್ ಕರಿ ವರ್ಸೊ ಏಣೆಲ್‌ದ ಅರಿ ಪೂರಾ ಕಾಲಿಯಾದುಪ್ಪುಂಡು. ಅಂಚಾದ್ [[ಆಟಿ]]ಡ್ ಕೆರೆಂಗ್, [[ತೇವು]], [[ತಜಂಕ್]], ಮೂಂಡಿ, [[ಉಪ್ಪಡ್ ಪಚ್ಚಿಲ್|ಉಪ್ಪಡಚ್ಚಿಲ್]], [[ಸಾಂತಣಿ]] ಇಂಚಿನ ಸೊತ್ತುಲೆನೇ ತಿಂದ್‌ದ್ ದಿನ ಕರಿಯುವ ಪರಿಸ್ಥಿತಿ. ಈ ಬಂಙನ್ ಪೊಸ ಮದಿಮಲ್ ಅನುಭವಿಸುನ ಬೊಡ್ಚಿ ಪಂಡ್‌ದ್ ಅಪ್ಪೆ ಇಲ್ಲಗ್ ಕಡಪುಡುನ ಕ್ರಮ ಸುರು ಆದುಪ್ಪು. === ಆಟಿ ಕುಲ್ಯರ ಲೆತೊಂದು ಪೋಪುನೆ === ಪೊಸ ಮದಿಮ್ಮಾಲೆ ಸುರತ್ತ ಆಟಿಗ್ ಅಪ್ಪೆ ಇಲ್ಲಡೆಗ್ ಅಪ್ಪೆ ಇಲ್ಲ್ದಕ್ಲ್ ಪೋದು ಲೆತ್ತೊಂದು ಬರ್ಪುನ ಕ್ರಮ. ಮದಿಮ್ಮಾಲೆನ್ ದಾಯೆ ಇಲ್ಲಡೆ ಲೆತೊಂದು ಬರ್ಪುನೆ? ಆಟಿಕುಲ್ಲುನೆಂದ್ ದಾಯೆ ಪನ್ಪೆರ್? ಇಂಚಪೂರ ಪ್ರಶ‍್ನೆಲು ಲಕ್ಕುವೊ. === ಆಟಿಗ್ ಲೆತೊಂದು ಪೋಪುನ ಉದ್ದೇಸೊ === ಆಟಿಡ್ ಸೀಕ್- ಸಂಕಟ ಜಾಸ್ತಿ. ಅಂಚಾದ್ ಪೊಸ ಮದಿಮಲ್ ಈ ಪೊರ್ತುಡು ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಇತ್ತ್‌ಂಡ ಆಲೆಗ್ ಮನಸ್‌ಗ್ ನೆಮ್ಮದಿ ತಿಕ್ಕು. ಅಂಚನೆ ಉಪಚಾರ ಮಲ್ಪೆರೆ ಅಪ್ಪೆಲಾ ತಿಕ್ಕುವೆರ್. ಅಲ್ಪ ಬಂಙ ಇತ್ತ್‌ಂಡಲಾ ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಪೊಣ್ಣು ಕಷ್ಟೊಡುಲಾ ಕುಸಿಡುಪ್ಪುವಲ್. ಮದಿಮೆದ ಸುರುಟೆ ಕಷ್ಟೊದ ಸಮಯೊಡು [[ಮಾಮಿ]] ಇಲ್ಲಡ್ ಇತ್ತಲ್‌ಂಡ ಆಲೆನ ಮನಸ್‌ಗ್ ಮಸ್ತ್ ಬೇಜಾರ್ ಆವು ಪನ್ಪಿನ ಕಾರಣೊಗಾದ್ ಅಪ್ಪೆ ಇಲ್ಲಡೆ ಕಡಪುಡುದು ಕೊರ್ಪಿನ ಸಂಪ್ರದಾಯ ಸುರು ಮಲ್ತ್‌ದುಪ್ಪೆರ್. ಆಟಿದ ದಿರಿಕೂಟ ಬೊಲ್ಲೊಗು, ಜಡಿ ಬರ್ಸೊಗು ಪೊಸ ಮದಿಮಲ್ ಮಾನಸಿಕವಾದ್ ಜಗ್ಗುನ ಬೊಡ್ಚಿ ಪನ್ಪಿನ ಉದ್ದೇಶಲಾ ಉಂದೆತ ಪಿರವುಡುಪ್ಪು. == ಆಟಿ ಸಮ್ಮನೊ == ಆಟಿ ಕುಲ್ಯರ ಬತ್ತ್‌ನ ಮಗಳೆನ್ ಕಂಡಾನಿ ಇಲ್ಲಡೆ ಲೆತೊಂದ್ ಪೋಪುನ ಕ್ರಮೊ ಉಂಡು. ಅಪಗ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡುಂದು ಪನ್ಪೆರ್. ಕಬಿತಡ್ ಇಂಚೊಂಜಿ ಪಾತೆರೊ ಉಂಡು, '''ಬರಾಂದಿ ಬಿನ್ನೆರ್ ಬತ್ತೆರ್ ಮಗ ಸೇಸೊ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡಾಂಡೆ'''. === ಆಟಿದ ನಂಬಿಕೆಲು === ಆಟಿಡ್ ಪೊಣ್ಣು [[ಬಾಲೆ]] [[ಮದಿಮಾಳ್ ಮದಿಮೆ|ಮದಿಮಾಲ್]] ಆಂಡ ಅನಿಷ್ಠ ಪನ್ಪಿ ನಂಬೊಲಿಕೆ ಉಂಡು. ಆಟಿಡ್ ಮದಿಮಲಾಯಿನ ಪೊಣ್ಣಗ್, ಸೀಕ್‌ದ ಜೋಕುಲೆಗ್, ಗೊಡ್ಡು ಪೆತ್ತಗ್, ಫಲಕೊರಂದಿ ತಾರೆಗ್ ಬುಕ್ಕೊ ಸಂತತಿ ಆವಂದಿ ಪೊಂಜೋವುಲೆಗ್ ಆಟಿ ಕಳೆಂಜಡ ತರೆಕ್ಕ್ ನೀರ್ ಮೈಪದ್ ಕಳೆಂಜಗ್ ದಾನೊ ಕೊರ್ಂಡ ಆ ಅನಿಷ್ಠ ಕಳೆಯುಂಡು, ಜೋಕುಲಾಪುಂಡು ಪಲ ದಿಂಜಿದ್ ಉರ್ಕರುಂಡು ಪನ್ಪಿ ನಂಬಿಕೆಲ ತುಳುನಾಡ್‌ಡ್ ಆಟಿಕಳೆಂಜ ಪಾಡ್ದಾನೊಡು ಬರ್ಪುಂಡು. === ಆಟಿದ ಗಾದೆಲು === # ಆಟಿಡ್ ಪೆದ್ದುನ ಬಾಲೆ ಪೊಣ್ಣು # ಆಟಿಡ್ ಕಂಡನಿ ಬುಡೆದಿ ಒಟ್ಟೂಗೆ ಇಪ್ಪರೆ ಆವಂದ್ === ಆಟಿದ ಕತ್ತಲೆ === ಆಟಿದ ಸಮಯೊಡು ಮಿನ್ಪುರಿ ಬರ್ಪುಂಡು. ಕರೆಂಟ್ ಇದ್ಯಾಂದಿ ಇಲ್ಲ್ದ ಸುತ್ತುಡೆ ಮಿನ್ಪರಿದ ಬೊಲ್ಪು ಅಪಾಪಗ ಮಿಂಚುಂಡು. ಅಯಿತ ನಡುಟ್ ಕರ್ಗುಡ ಕತ್ತಲೆ ಬರ್ಪುಂಡು. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ಜಾನಪದ]] [[ವರ್ಗೊ:ತುಳುನಾಡ ಸಂಸ್ಕೃತಿ]] kj9dwwbfnbz8ozwcthcdosxeua710or ಉಲ್ಲಾಕುಳು 0 3674 360709 280662 2026-05-16T07:03:31Z ChiK 1136 360709 wikitext text/x-wiki [[ಫೈಲ್:ಉಳ್ಳಕುಲು.JPG|thumb|upright|ಉಲ್ಲಾಕುಲು]] [[File:ಉಳ್ಳಾಕುಲು ನೇಮ.jpg|thumb|ಉಳ್ಳಾಕುಲು ನೇಮ]] '''ದೇವಇರ್ವೆರ್‌ರ್ ಎಂಕ್ಲು ಉಳ್ಳಾಕ್ಲು. ಎಂಕ್ಲೆನ್ ರಾಮೆಲಕ್ಷ್ಮಣೆಂದ್ ಪನ್ಪೆರ್''' ಇಂಚ ಉಳ್ಳಾಕ್ಲು ದೈವೊ ನುಡಿಕಟ್ಟ್ ಪನ್ಪುಂಡು. ಸುಳ್ಯೊಡು ಉಳ್ಳಾಕ್ಲೆನ ದೈವಸ್ತಾನೊ ಉಂಡು. ಮಂಡೆಕೋಲು ಗ್ರಾಮೊದ ಪೇರಾಲ್ಡ್ ಇಂದೆನ ಮಾಡೊ ಉಂಡು. [[ಪತ್ತನಾಜೆ]]ಗ್ ಪೇರಾಲ್ದ ಬಜಪ್ಪಿಲಡ್ ಅಕೇರಿದ ನೇಮೊ ಪ್ರತೀ ವರ್ಸೊ ನಡತ್ತೊಂದುಂಡು. ಕೊಡಿ ತೊಡಿಕಾನ ಕಡೆ ಬಜಪ್ಪಿಲಂದ್ ಇನಿಲಾ ನುಡಿಕಟ್ಟ್ ಆಪುಂಡು. ಕೆಲವು ಜಾಗೆಡ್ ಅಣ್ಣದೈವ ಬುಕ್ಕೊ ತಮ್ಮ ದೈವಗ್ ನೇಮ ಅಂಡ ಬುಕ್ಕೊ ಕೆಲವು ಜಾಗೆಡ್ ಒಂಜೇ ದೈವಗ್ ನೇಮ ನಡಪುಂಡು. ಒಂಜಿ ಆವಡ್ ರಡ್ಡ್ ನೇಮ ಆವಡ್ ಈ ದೈವನ್ ಉಳ್ಳಾಕುಲು/ಉಲ್ಲಾಕುಲು ಪಂದೇ ಲೆಪ್ಪುವೆರ್.<ref>{{cite news |title=ಮಾ.19 ರಂದು ಮಂಗಳೂರಿನಲ್ಲಿ ಉಲ್ಲಾಕುಳು ಆರಾಧನೆ ಅನನ್ಯತೆ ಕೃತಿ ಬಿಡುಗಡೆ |url=https://sullia.suddinews.com/archives/855360 |access-date=16 May 2026 |work=Suddi Sullia |date=16 March 2026}}</ref> == ಪದತ್ತ ವಿವರಣೆ == ಉಲ್ಲಾಕುಲು ಪಂಡ ಉಲ್ಲಾಯ + ನಕುಲು. ಪಂಡ ಇರುವೆರ್. ಉಳ್ಳಾಯ ಪಂಡ ಉಪ್ಪುನಾಯೆ ಯಜಮಾನೆ ಪನ್ಪುನ ಅರ್ತೊಡು ಪ್ರಾಯೋಗ ಅಪುಂಡು. ದುಂಬು ಅರಸುನಕುಲೆನ್, ಊರುದ ಗುರಿಕಾರನ್, ಗುತ್ತುದ ಒಡೆಯನ್ ಉಳ್ಳಾಯ ಪಂಡ್ಂದ ಒಡತಿನ್ ಉಳ್ಳಾಲ್ತಿ ಪಂದ್ ಲೆತ್ತೊಂದು ಇತ್ತೆರ್. ಅಂಚಾದ್ ಉಳ್ಳಾಕುಲು ಪಂಡ ಒಡೆಯೇ ಪನ್ಪುನ ಅರ್ತೊ ಮೂಲು ಬರ್ಪುಂಡು. == ದೈವೊದ ಪುಟ್ಟು == == ವಿದೊ == # ಎಲ್ಯ ಉಲ್ಲಾಕುಲು # ಮಲ್ಲ ಉಲ್ಲಾಕುಲು # ಇರ್ವೆರ್ ಉಲ್ಲಾಕುಲು # ನಾಲ್ವೇರ್ ಉಲ್ಲಾಕುಲು # ಐವೇರ್ ಉಲ್ಲಾಕುಲು == ಚರಿತ್ರೆ == == ಅಡ್ಡಣ ಪೆಟ್ಟ್ == [[ಫೈಲ್:Shield-0.jpg|thumb|ಅಡ್ಡಣೊ]] [[ಫೈಲ್:Shield-1.jpg|thumb|ಅಡ್ಡಣ]] [[ಫೈಲ್:Redy to fait.jpg|thumb|ಅಡ್ಡಣ ಪೆಟ್ಟ್]] == ಸಂಧಿ == == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ಭೂತಾರಾಧನೆ]] [[ವರ್ಗೊ:ಭೂತೊಲು]] [[ವರ್ಗೊ:ದೈವೊಲು]] j59jbwsjaml3im7xw0jj6gnp9d9tz5a ಕಾರ್ತಿಂಗೊಲು 0 3795 360713 359057 2026-05-16T07:17:25Z ChiK 1136 added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360713 wikitext text/x-wiki [[ತುಳುನಾಡ್|ತುಳು]]ತ ನಾಲನೆ ತಿಂಗೊಲು ಕಾರ್ತಿಂಗೊಲು. ಇಂದೆನ್ ಕಾರ್ತ್ಯೊಲುಂದು ಪನ್ಪೆರ್. ಕಾರ್ತಿಂಗೊಲುಲಾ ಕಾರ್ತ್ಯೊಲುಲಾ ರಡ್ಡಲಾ ಒಂಜೇ. ಕಾರ್ತೆಲ್, ಕಾರ್ತಿಂಗೊಲು, ಕಾರ್ತ್ಯೊಲು ಇಂಚ ಈ ತಿಂಗೊಲುನು ಪನ್ಪೆರ್. == ಕಾರ್ತಿ/ಕಾರ್ == ಸೌರಮಾನೊದ ಮೂಜನೆ ತಿಂಗೊಲುದ ಪುದರ್. ಮರಿಯಾಲೊ ಸುರು ಆಪಿನೆಕ್ ದುಂಬುದ ತಿಂಗೊಲು. ಕಾರ್ ಪನ್ಪುನ ಪದೊ ಬೇತೆ ಬಾಸೆಲೆಡ್ ಉಂಡು. ಇಂದೆತ ಅರ್ತೊ cloud, rain season * ತಮಿಳು : ಕಾರ್ * ಮಲಯಾಳಿ : ಕಾರ್ * ಕೊಂಕಣಿ : ಕರ್ * ಕನ್ನಡ : ಕಾರ್/ಕಾರ್ತಿ * ತೆಲುಗು : ಕಾರು == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್ || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ಕಾರ್ತಿ ಪದೊ ತುಳುಟ್ ಗಳಸ್‌ನ ಬಗೆ == * ಕಾರ್ತಿದ ಬುಲೆ : ಕಾರ್ತಿಂಗೊಲುಡು ನಡ್‍ದ್ ಮಲ್ಪುನ ಬುಲೆ. * ಕಾರ್ತಿದ ಮಲಕ : ಕಾರ್ ತಿಂಗೊಲುಡು ಬರ್ಪುನ ಬಿರುಗಾಳಿ; ಮುಂಗಾರ್ ಬರ್ಸೊದೊಟ್ಟುಗು ಬರ್ಪುನ ಬಿರ್ಗಾಳಿ. * ಕಾರ್ತಿಕೊ : ಚಾಂದ್ರಮಾನದ ಎನ್ಮನೆ ತಿಂಗೊಲು.<ref>'''ತುಳು ನಿಘಂಟು : ಸಂಪುಟ ಎರಡು'''; ೧೯೯೨. (''ತುಳು-ಕನ್ನಡ-ಇಂಗ್ಲಿಷ್ ಶಬ್ದಕೋಶ''), ಪ್ರಧಾನ ಸಂಪಾದಕೆರ್ '''ಡಾ.ಯು.ಪಿ.ಉಪಾಧ್ಯಾಯ''', ''ರಾಷ್ಟ್ರಕವಿ ಗೋವಿಂದ ಪೈ ಸಂಶೋಧನ ಕೇಂದ್ರ, ಎಂ.ಜಿ.ಎಂ. ಕಾಲೇಜು ಆವರಣ, ಉಡುಪಿ, ಕರ್ನಾಟ''ಕ</ref> == ನಂಬಿಕೆ == * ಕಾರ್ತಿಕ ಮಾಸೊದ ಚತುರ್ದಶಿಡ್ ಮೀಂಡ ಸೊರ್ಗೊ ತಿಕುಂಡುಗೆ. * ಕಾರ್ತಿಕ ಪೂಜೆ : ದೇವೆರ್‍ನ ಎದುರುಡು ಸಾಲ್ ದೀಪೊ ದೀಡ್ದ್, ನೆವೇದ್ಯೊ ಸಮರ್ಪಣೆ ಮಾಲ್ತ್ ನಡಪಾವುನ ಒಂಜಿ ಇದೊತ ಪೂಜೆ. * ಕಾರ್ನವೆ/ಕಾರ್ನೆರ್ : ಕುಟುಂಬೊದ ಹಿರಿಮಾನ್ಯೆ, ಯಜಮಾನೆ. ತೀರ್ದ್ ಪೋಯಿನ ಹಿರಿಮಾನ್ಯೆ. ಗುರುಕಾರ್ನವೆ. * ಕಾರ್ನವೆರೆಗ್ ಬಲಸುನೆ : ಸೈತಿನ ಹಿರಿಮಾನ್ಯೆರೆಗ್ ಕಾಲಾದಿಗ್ ಬಲಸುನ ಕೋರಿ ತಮ್ಮನೊ ಒನಸ್. ಕಾರ್ನೆರೆ ಅಗೆಲ್ಂದ್‍ಲಾ ಪನ್ಪೆರ್. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[Category:ತುಲು ತಿಂಗೊಲು]] [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] rnlqynhnbiqv3u4zcwbuklosdvxqj4v 360714 360713 2026-05-16T07:17:41Z ChiK 1136 removed [[Category:ತುಲು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360714 wikitext text/x-wiki [[ತುಳುನಾಡ್|ತುಳು]]ತ ನಾಲನೆ ತಿಂಗೊಲು ಕಾರ್ತಿಂಗೊಲು. ಇಂದೆನ್ ಕಾರ್ತ್ಯೊಲುಂದು ಪನ್ಪೆರ್. ಕಾರ್ತಿಂಗೊಲುಲಾ ಕಾರ್ತ್ಯೊಲುಲಾ ರಡ್ಡಲಾ ಒಂಜೇ. ಕಾರ್ತೆಲ್, ಕಾರ್ತಿಂಗೊಲು, ಕಾರ್ತ್ಯೊಲು ಇಂಚ ಈ ತಿಂಗೊಲುನು ಪನ್ಪೆರ್. == ಕಾರ್ತಿ/ಕಾರ್ == ಸೌರಮಾನೊದ ಮೂಜನೆ ತಿಂಗೊಲುದ ಪುದರ್. ಮರಿಯಾಲೊ ಸುರು ಆಪಿನೆಕ್ ದುಂಬುದ ತಿಂಗೊಲು. ಕಾರ್ ಪನ್ಪುನ ಪದೊ ಬೇತೆ ಬಾಸೆಲೆಡ್ ಉಂಡು. ಇಂದೆತ ಅರ್ತೊ cloud, rain season * ತಮಿಳು : ಕಾರ್ * ಮಲಯಾಳಿ : ಕಾರ್ * ಕೊಂಕಣಿ : ಕರ್ * ಕನ್ನಡ : ಕಾರ್/ಕಾರ್ತಿ * ತೆಲುಗು : ಕಾರು == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್ || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ಕಾರ್ತಿ ಪದೊ ತುಳುಟ್ ಗಳಸ್‌ನ ಬಗೆ == * ಕಾರ್ತಿದ ಬುಲೆ : ಕಾರ್ತಿಂಗೊಲುಡು ನಡ್‍ದ್ ಮಲ್ಪುನ ಬುಲೆ. * ಕಾರ್ತಿದ ಮಲಕ : ಕಾರ್ ತಿಂಗೊಲುಡು ಬರ್ಪುನ ಬಿರುಗಾಳಿ; ಮುಂಗಾರ್ ಬರ್ಸೊದೊಟ್ಟುಗು ಬರ್ಪುನ ಬಿರ್ಗಾಳಿ. * ಕಾರ್ತಿಕೊ : ಚಾಂದ್ರಮಾನದ ಎನ್ಮನೆ ತಿಂಗೊಲು.<ref>'''ತುಳು ನಿಘಂಟು : ಸಂಪುಟ ಎರಡು'''; ೧೯೯೨. (''ತುಳು-ಕನ್ನಡ-ಇಂಗ್ಲಿಷ್ ಶಬ್ದಕೋಶ''), ಪ್ರಧಾನ ಸಂಪಾದಕೆರ್ '''ಡಾ.ಯು.ಪಿ.ಉಪಾಧ್ಯಾಯ''', ''ರಾಷ್ಟ್ರಕವಿ ಗೋವಿಂದ ಪೈ ಸಂಶೋಧನ ಕೇಂದ್ರ, ಎಂ.ಜಿ.ಎಂ. ಕಾಲೇಜು ಆವರಣ, ಉಡುಪಿ, ಕರ್ನಾಟ''ಕ</ref> == ನಂಬಿಕೆ == * ಕಾರ್ತಿಕ ಮಾಸೊದ ಚತುರ್ದಶಿಡ್ ಮೀಂಡ ಸೊರ್ಗೊ ತಿಕುಂಡುಗೆ. * ಕಾರ್ತಿಕ ಪೂಜೆ : ದೇವೆರ್‍ನ ಎದುರುಡು ಸಾಲ್ ದೀಪೊ ದೀಡ್ದ್, ನೆವೇದ್ಯೊ ಸಮರ್ಪಣೆ ಮಾಲ್ತ್ ನಡಪಾವುನ ಒಂಜಿ ಇದೊತ ಪೂಜೆ. * ಕಾರ್ನವೆ/ಕಾರ್ನೆರ್ : ಕುಟುಂಬೊದ ಹಿರಿಮಾನ್ಯೆ, ಯಜಮಾನೆ. ತೀರ್ದ್ ಪೋಯಿನ ಹಿರಿಮಾನ್ಯೆ. ಗುರುಕಾರ್ನವೆ. * ಕಾರ್ನವೆರೆಗ್ ಬಲಸುನೆ : ಸೈತಿನ ಹಿರಿಮಾನ್ಯೆರೆಗ್ ಕಾಲಾದಿಗ್ ಬಲಸುನ ಕೋರಿ ತಮ್ಮನೊ ಒನಸ್. ಕಾರ್ನೆರೆ ಅಗೆಲ್ಂದ್‍ಲಾ ಪನ್ಪೆರ್. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 5gmfiucfgu6kvuhqtrbwig86xzvfohn ಜಾರ್ತೆ 0 4224 360718 359062 2026-05-16T07:19:05Z ChiK 1136 removed [[Category:ತುಲು ತಿಂಗೊಲು]]; added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360718 wikitext text/x-wiki [[ತುಳು]]ತ ಎನ್ಮೊನೆ ತಿಂಗೊಲು '''ಜಾರ್ತೆ'''. ಜಾರ್ದೆಂದ್ ಕೆಲವು ಕಡೆಟ್ ಪನ್ಪೆರ್. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಲುತ ತಿಂಗೊಲು == {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || ಜಾರ್ದೆ || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == == ಉಲ್ಲೇಕೊಲು == {{Reflist}} {{ಉಲ್ಲೇಕೊ}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] hltlxz8bkhtbq7vfap6gzz2ubhmyazp ತುಳು ತಿಂಗೊಲು 0 4293 360723 359554 2026-05-16T07:20:59Z ChiK 1136 removed [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360723 wikitext text/x-wiki '''ತುಳು''' ತುಳುನಾಡ್‍ದ ಜನೊಕ್ಲೆ ಇಲ್ಲದ ಬಾಸೆ. ತುಳುವೆರೆನ ತಿಂಗೊಲುದ ಲೆಕ್ಕೊ ಕನ್ನಡೊದಕ್ಲೆ ಲೆಕೊ ಅತ್ತ್. ಭಾರತೀಯೆರ್ ಜನವರಿಡ್ದ್ ದಶಂಬರೊಗು ಮುಟ್ಟ ಪದ್ರಾಡ್ ತಿಂಗೊಲುನು ಲೆಕ್ಕೊಗು ದೆತೊನುವೆರ್. ತುಳುವೆರೆಗೆ ತಿಂಗೊಳು ಸುರುವಾಪುನೆನೆ ಪಗ್ಗುಡ್ದು. ನಮ್ಮ ಸಾಲೆದ ಲೆಕ್ಕಾಚಾರೊಡು ಎಪ್ರಿಲ್-ಮೇ ತಿಂಗೊಲಾಪುಂಡು. ಎಪ್ರಿಲ್ ತಿಂಗೊಲ್ದ ಅರ್ದೊಡ್ದ್ ಸುರುವಾದ್ ಮೇ ತಿಂಗೊಲ್ದ ಅರ್ದೊಡು ಪಗ್ಗು ಮುಗಿಪುಂಡು. ಪಗ್ಗುಡ್ದ್ (ಎಪ್ರಿಲ್-ಮೇ), [[ಬೇಶ]](ಮೇ-ಜೂನ್), [[ಕಾರ್ತೆಲ್]](ಜೂನ್ - ಜುಲಾಯಿ), [[ಆಟಿ]](ಜುಲೈ-ಆಗೋಸ್ಟು), [[ಸೋಣ]](ಆಗಸ್ಟ್ - ಸೆಪ್ಟೆಂಬರ, ನಿರ್ನಾಲೊ(ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ), ಬೊಂತ್ಯೊಲ್‌/ಬೊಂತೆಲ್ (ಅಕ್ಟೋಬರ್-ನವೆಂಬರ್), [[ಜಾರ್ದೆ]](ನವೆಂಬರ–ದಸಂಬರ), ಪೆರಾರ್ದೆ(ಡಿಸೆಂಬರ್-ಜನವರಿ, ಪೊಣ್ಣಿ/ಪುಯಿಂತೆಲ್ (ಜನವರಿ ವರ್ಷಾರಂಭ-ಫೆಬ್ರವರಿ), ಮಾಯಿ(ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್), [[ಸುಗ್ಗಿ]] (ಮಾರ್ಚ್-ಎಪ್ರಿಲ್). ಇಂಚ ತುಳುವೆರೆಗ್ 12 ತಿಂಗೊಲು. '''[[ಬಿಸು ಪರ್ಬ|ಬಿಸು]]''' ಸಂಕ್ರಾಂತಿದ ಮನದಾನಿ ಪಗ್ಗು ತಿಂಗೊಲುಡು ಪೊಸ ಒರ್ಸೊ ಸುರು. ರಡ್ಡನೇ ತಿಂಗೊಲು ಬೇಸ. ಈ ತಿಂಗೊಲುದ ಪತ್ತನೆ ದಿನೊ '''[[ಪತ್ತನಾಜೆ]]'''. ಪತ್ತನಾಜೆಡ್ದ್ ಬುಕ್ಕೊ ಮರಿಯಾಲೊ. ಹೆಚ್ಚಾದ್ ಮರಿಯಾಲೊ ಸುರು ಆಪುನ ಪೊರ್ತುನು ಒರ್ಸೊಗಟ್ಟಲೆ ಕುಲ್ಲುದು ಲೆಕ್ಕ ಪಾಡ್ದ್ ನಮ್ಮ ಹಿರಿಯಾಕ್ಲ್ ಈ ಪತ್ತನಾಜೆ ಪನ್ಪಿನ ಒಂಜಿ ಗಡುಗು ನಿಗಂಟ್ ಮಲ್ದೆರ್. ಅಂಚಾದ್ 'ಪತ್ತನಾಜೆದಾನಿ ಪತ್ತ್ ಪನಿ' ಪನ್ಪಿನ ಅನುಭವೊದ ಪಾತೆರ ಉಂಡು. ಪತ್ತನಾಜೆ ಕರಿಂಡ ಬುಕ್ಕೊ ಮರಿಯಾಲ ಪನ್ಪಿನ ಲೆಕ್ಕ. ಈ ವರ್ಸೊ ಪತ್ತನಾಜೆ ಉಂದೇ ಮೇ ತಿಂಗೊಲುದ 24 ತಾರೀಕ್ಗ್ ಬರ್ಪುಂಡು. [[ತುಳುವೆರ್|ತುಳುವೆರೆ]]ಗ್ [[ಸುಗ್ಗಿ]] ಅಕೇರಿದ ತಿಂಗೊಲು. [[ಪಗ್ಗು]]ಡ್ದು ಬುಕ್ಕೊ ಪೊಸ ತಿಂಗೊಲು. '''ತುಳು ತಿಂಗೊಲು'''ಲು ಇಂಚ ಉಂಡು.<ref>http://web.archive.org/save/http://vijaykarnataka.indiatimes.com/home/languages/tulu/-/articleshow/35025902.cms</ref> == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable sortable" !scope="col" |ಕ್ರಮ ಸಂಕ್ಯೆ. !scope="col" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] !scope="col" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] !scope="col" |ಶಾಲಿವಾಹನ ಶಕ !scope="col" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] !scope="col" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] !scope="col" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] !scope="col" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] !scope="col" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- |1. |[[ಪಗ್ಗು]] |Mēṭam |[[:en:Meṣa|ಮೇಷ]] |ಚೈತ್ರ-ವೈಶಾಖ |Chithirai |Aries |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- |2. |[[ಬೇಸ]] |Iṭavam |[[:en:Vṛṣabha|ವೃಷಭ]] |ವೈಶಾಖ-ಜೇಷ್ಠ |Vaikasi |Taurus |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- |3. |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] |Mithuṉam |[[:en:Mithuna (month)|ಮಿಥುನ]] |ಜೇಷ್ಠ-ಆಶಾಡ | Aani |Gemini |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- |4. |[[ಆಟಿ]] |Kaṟkkaṭakam |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] |ಆಶಾಡ-ಶ್ರಾವಣ | Aadi |Cancer |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ |ಮೊಹರಂ-ಸಫರ್ |- |5. |[[ಸೋಣೊ]] |Chingam |[[:en:Siṃha|ಸಿಂಹ]] |ಶ್ರಾವಣ-ಬಾದ್ರಪದ |Aavani |Leo |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ |ಸಫರ್-ರಬಿಲಾವಲ್ |- |6. |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ |Kaṉṉi |[[:en:Kanyā|ಕನ್ಯಾ]] |ಬಾದ್ರಪದ-ಅಶ್ವಿಜ |Purattasi |Virgo |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- |7. |[[ಬೊಂತ್ಯೊಲು]] |Thulām |[[:en:Tulā|ತುಲಾ]] |ಅಶ್ವಿಜ-ಕಾರ್ತಿಕ |Aippasi |Libra |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- |8. |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] |Vr̥śchikam |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] |ಕಾರ್ತಿಕ-ಮಾರ್ಗಶಿರ |Karthigai |Scorpio |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- |9. |[[ಪೆರಾರ್ದೆ]] |Dhaṉu |[[:en:Dhanu (month)|ಧನು]] |ಮಾರ್ಗಶಿರ-ಪುಷ್ಯ |Margazhi |Sagittarius |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- |10. |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ |Makaram |[[:en:Makara (month)|ಮಕರ]] |ಪುಷ್ಯ-ಮಾಘ |Thai |Capricorn |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ |ರಜಬ್-ಶಾಬಾನ್ |- |11. |[[ಮಾಯಿ]] |Kumbham |[[:en:Kumbha (month)|ಕುಂಭ]] |ಮಾಘ-ಪಾಲ್ಗುಣ |Maasi |Aquarius |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- |12. |[[ಸುಗ್ಗಿ]] |Meeṉam |[[:en:Mīna|ಮೀನ]] |ಪಾಲ್ಗುಣ-ಚೈತ್ರ |Panguni |Pisces |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತಿಂಗೊಲ್ದುದ್ಯೆ == ಸಂಕ್ರಾಂತಿದ ಮನತ್ತಾನಿ ತಿಂಗೊಲ್ದುದ್ಯೆ. ತಿಂಗೊಲುದ ಸುರೂತ ದಿನೊಕು ತಿಂಗೊಲ್‍ದ+ಉದ್ಯೆ ಪನ್ಪೆರ್. ಇನಿ ಇಲ್ಲಡ್ದ್ ಪೆಟ್ಯೆದ ಬಾಕ್ಲ್ ದೆಪ್ಪುಜೆರ್. ಎರೆಗ್‍ಲಾ ದುಡ್ಡು, ಬಿತ್ತ್, ಇಂಚ ದಾಲಾ ಕೊರ್ಪುಜೆರ್. ತಿಂಗೊಲ್ದುದ್ಯೆದಾನಿ ಕಾಸ್ ಕೊರಂಡ ಬುಕ್ಕೊ ಇಡೀ ತಿಂಗೊಲುಲಾ ಕರ್ಚಾಪುಂಡುದು ನಂಬುವೆರ್. ಇನಿ ಏತಾಂಡಲಾ ಉಲಯಿ ಪೆಟ್ಟ್‍ದ ದಿನೊ. ಅಂಚನೇ ಸುಬಕಾರ್ಯೊಗ್‍ಲಾ ತಿಂಗೊಲ್ದುದ್ಯೆ ಎಡ್ಡೆತ್ತ್‌ಂದ್ ಪನ್ಪೆರ್. == ತುಳುವೆರೆ ತಿಂಗೊಲ್ದ ಪರ್ಬೊಲು ಬುಕ್ಕೊ ಎಡ್ಡೆ ದಿನೊಕುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲುಡು ಬರ್ಪುನ ಪರ್ಬೊಲು ಬುಕ್ಕೊ ಎಡ್ಡೆದಿನೊಕ್ಲೆನ ವಿವರೊ. <ref>{{Cite news |url=https://vanihegde.wordpress.com/2013/06/20/9220/ |title=ತುಳು ಭಾಷೆದ ಪೊರ್ಲು . |date=2013-06-20 |work=Vani Hegde's Blog |access-date=2026-04-21 |language=en-US |archive-date=2015-12-29 |archive-url=https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/ |url-status=dead }}</ref> * ತುಳುನಾಡ್‍ಡ್ ಆಜಿ ತಿಂಗೊಲು [[ಮರಿಯಾಲೊ]]. ಆಜಿ ತಿಂಗೊಲು [[ಅರೆಗಾಲೊ]]. ಉಂದು ದುಂಬುದ ಕಾಲೊದ ಲೆಕ್ಕೊ. ಇತ್ತೆ ಎಚ್ಚಿ ಕಮ್ಮಿ ಇಂಚನೇ ಉಂಡು. ಆ ಕಾಲೊಡು ಮುಲ್ಪದ ಮರಿಯಾಲ ಪಂಡ ನಾಲೈನ್ ತಿಂಗೊಲು ಬುಡಂದೆ ಬರ್ಪುನ ಜಿರಿಕೂಟ ಬರ್ಸೊ. ಗಾಳಿ, ಮೆಂಚಿ, ತೆಡಿಲ್ ಇಂಚ ಮಾರಿ ಬೋಲ್ಲೊ ಬರ್ಪುಂಡು. ಅಂಚಾದ್ ಮರಿಯಾಲೊಡು ಮುಲ್ಪ ವಾ ರೀತಿದ ಗೌಜಿ, ಗಮ್ಮತ್ತ್, ಜಾತ್ರೆ, ಅಂಕ ಆಯನ ಮಲ್ಪುಲೆಕನೇ ಇದ್ದಿ. ಅಯಿಕಾದೇ ಪತ್ತನಾಜೆದಾನಿ ಈ ಮಾತಾ ಗೌಜಿಲೆನ್ ಕೈದ್ ಮಲ್ಪುನ ನಿರ್ಧಾರ ಮಲ್ತೆರ್. ಅಂಚ ಪತ್ತನಾಜೆಗ್ ಬಾರೀ ಮಹತ್ವ ಬತ್ತ್ಂಡ್. * ತುಳು ಪರಂಪರೆದ ಪ್ರಕಾರ ಪತ್ತನಾಜೆಡ್ದ್ ಬುಕ್ಕೊ ಜಾತ್ರೆ, ನೇಮ-ನೆರಿ, ಕೋಲೊ, ತಂಬಿಲ, ಅಗೆಲ್, ಆಟೊ, ನಾಟಕ ಒವುಲಾ ಇಜ್ಜಿ. ಪತ್ತನಾಜೆದಾನಿ ಮಾತಾ ದೇವಸ್ಥಾನೊಡುಲಾ ಇಸೇಸೊ ಉಚ್ಚಯೊನು ಉಂತಾವೆರ್. ಬುಕ್ಕೊ ನಿತ್ಯ ಪೂಜೆ ಮಾತ್ರೊ. ಆಟೊದಕ್ಲು ಪತ್ತನಾಜೆದಾನಿ ಬನ್ನೊ ಬಿಚ್ಚಾವೆರ್. ಬೂತೊ ಕಟ್ಟುನಕುಲು ಪತ್ತನಾಜೆದಾನಿ ಗಗ್ಗರೊ ಗಿಚ್ಚುವೆರ್. ಊರುದ ದೈವ, ಇಲ್ಲದ ದೈವ, ಕುಟುಮೊದ ದೈವೊಲೆಗ್ ಕೊರ್ಪಿನ ತಮ್ಮನೊ ಪೂರಾ ಪತ್ತನಾಜೆದಾನಿಗ್ ಕೈದ್. {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] !! ನುಡಿಕಟ್ಟುಲು |- | ೦೧ || [[ಪಗ್ಗು]] || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ, [[ಗೋಂದೊಲು ಪೂಜೆ]] || || ಪಗ್ಗುಡೆ ಎರು ಕಟ್ಟ್‌ದ್ ಅಡತೊನ್‌ಲ, ಬಗ್ಗ್‌ದ್ ನೇಜಿನ್ ಪಾಡೊನ್‌ಲ |- | ೦೨ || [[ಬೇಸ]]/ಬೇಸ್ಯ, ಬೇಸ್ಯೊ || [[ಪತ್ತನಾಜೆ]], ಬೂತಕೋಲೊ ನೇಮೊಲೆಗ್ ಅಕೇರಿ, [[ಗೋಂದೊಲು ಪೂಜೆ]] ||ಬೇಸದ ಬೆಪ್ಪುಡು ಊರುಮಾತ ಉರಿಪೋಂಡು || ಕೊರ್ಪಿಂಚಿ ಜೇವು ಸುಗ್ಗಿಪಗ್ಗುಡು ಕೊರ್ದು ಪೋತುಂಡು, ಮಾರಿಂಚಿ ಎರು ಬೇಸ್ಯದ ಬೆನ್ನಿಗ್ ಮಾರ್ದ್ ಪೋತುಂಡು |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]]<ref>{{cite book |last1=U. P. |first1=Upadhyaya |title=TULU LEXICON VOL.TWO |date=1992 |pages=770 |publisher=Rashtrakavi Govind Pai Samshodhana Kendra |location=[[:en:Mahatma Gandhi Memorial College|M.G.M College]] Udupi, 576102, Karnataka, India |edition=First}}</ref> || [[ಗುರುಕಾರ್ನೆರ್‌]]ಗ್ ಬಲಸುನೆ || ಕಾರ್ನವೆರಗ್ ಬಲಸುನೆ(ಕುಟುಮ್ಮೊದ ಹಿರಿಯೆರ್ ತೀರ್ದ್ ಪೋಯಿನಕ್ಲೆಗ್ ಬಳಸುನೆ) || ಕಾರ್ತಿದ ಬುಲೆ, ಕಾರ್ತಿದ ಮಲಕೊ |- | ೦೪ || ಕರ್ಕಾಟಕ ಮಾಸ-ಆಷಾಢ-[[ಆಟಿ]],<ref>{{cite book |last1=U. P. |first1=Upadhyaya |title=TULU LEXICON VOL.ONE |date=1988 |pages=228 |publisher=Rashtrakavi Govind Pai Samshodhana Kendra |location=[[:en:Mahatma Gandhi Memorial College|M.G.M College]] Udupi, 576102, Karnataka, India |edition=First}}</ref> || [[ಕನ್ನಿ ನಲಿಕೆ]]<ref>{{cite book |last1=Rāmakr̥ṣṇa Ācār |first1=Pāltāḍi |title=Tuḷunāḍina janapada pradarśana kalegaḷu |date=2017 |publisher=Vistaraṇe hāgu Salahā Kēndra, Karnāṭaka Janapada Viśvavidyālaya |location=Goṭagōḍi, Śiggāvi Tā., Hāvēri Jille |isbn=978-93-83149-54-4 |pages=243 |edition=First}}</ref>, [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], [[ಆಟಿಕುಲ್ಲುನೆ|ಆಟಿ ಕುಲ್ಲುನೆ]], [[ಆಟಿದ ಅಗೆಲ್]], [[ಆಟಿ ಅಮಾಸೆ|ಆಟಿದ ಅಮಾಸೆ]], ಆಟಿದ ದೊಂಬು, ಆಟಿದ ಪೆಲಕ್ಕಾಯಿ, ಆಟಿದ ಪರ್ಬ, [[ಆಟಿತಪ್ಪು|ಆಟಿಸಪ್ಪು]], [[ಮರ್ವೆ ನಲಿಕೆ]], [[ಮರ್ದೆ ನಲಿಕೆ]], [[ಬೇಡನ್|ಬೇಡನ್ ನಲಿಕೆ]] || ಆಟಿದ ದೊಂಬು ಆನೆದ ಬೆರಿ ಪುಡಾವು, ಆಟಿ ಆಡೋಣ್ತ್ ಪೋಪುಂಡು, ಸೋಣೊ ಸೋಡೋಣ್ತ್ ಪೋಪುಂಡು || ಆಟಿ ತಿಂಗೊಲುಡು ಒರ್ಲ ಚಡ್ದ್ ಇತ್ತಿನಾಯೆ ಪಿದಯಿ ಪೋವಾಯೆ(ಆಟಿ ತಿಂಗಳಲ್ಲಿ ಒಂದು ಬಳ್ಳ ದಡ್ಡ್ ಬತ್ತ್ ಇದ್ದವನು ಹೊರ ಹೋಗನು), ಆಟಿಡ್ ಅಗೆಲ್ ಸೋಣೊಡು ಕೋಲೊ |- | ೦೫ || [[ಸೋಣೊ]]/ಸೋನೊ/ಚೋಣೊ ಸಿಂಹಮಾಸ || [[ಚೌತಿ ಪೂಜೆ|ಚೌತಿ]], [[ಅಸ್ಟೆಮಿ|ಅಷ್ಟೆಮಿ]] ಪರ್ಬೊ, [[ಸೋಣದ ಜೋಗಿ|ಸೋಣತ ಜೋಗಿ]] ನಲಿಕೆ, [[ಜೋಗಿ ಪುರುಷ ನಲಿಕೆ]] || [[ಆಟಿ]] ಆಡೋಂದ್ ಪೋಡ್, ಸೋಣೊ ಸೋಡೋಂದ್ ಪೋಂಡ್ || ಕಜಿಪ್ಪೆಂಚಿ ಸೇನೆರೆ? ಸೋನೆತಪ್ಪುದ ಸಾರ್, ಸೋಣೊದ ಪುಣ್ಣಮೆ, ಸೋಣೊದ ಅಜ್ಜಿ ಗಿಡಪುನೆ, ಸೋಣ ತುಡರ್ ಸೋಣೆತಪ್ಪು, ಸೋಣೊ ತಿಂಗೊಲುಡು ಸೊರ್ಗೊದ ಬಾಕಿಲ್ ದೆಪ್ಪುನೆಗೆ |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]]/ನಿರ್ನಾಲ್/ಕನ್ಯಾಮಾಸ || [[ಪೊಲ್ಸೊಡಿ ಪೋಪುನೆ]], [[ಕಾವೇರಿ ಸಂಕ್ರಾಂತಿ|ಕಾವೋರಿ ಸಂಕ್ರಾಂತಿ]], [[ಎರುಕೋಲೊ]], [[ಪುದ್ದಾರ್|ಪುದ್ವಾರ್]], ಏನೆಲ್ ಬೆನ್ನಿದ ಅಕೇರಿದ ತಿಂಗೊಲು, ಏಣೆಲ್‌ದ ಕೊಯಿಲ್‌, [[ಮೂರ್ಲೆ ನಲಿಕೆ]] || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]]/ಬೊಂತೆಲ್/ಬೊಂತ್ಯೆಲ್<ref>{{cite book |last1=Upadhyaya |first1=Uliyar Padmanabha |title=Tuḷu nighaṇṭu: Tuḷu-kannaḍa-iṅgliś śabdakōśa |date=1997 |publisher=Rāṣṭrakavi Gōvinda Pai saṃśōdhana kendra |location=Udupi (Bhārata) |isbn=81-86668-20-9 |pages=2399}}</ref>|| [[ಮಾಂಕಾಳಿ ನಲಿಕೆ]], [[ಕಂಡೊಕೋರಿ|ಕಂಡೊಕೋರಿ ನಲಿಕೆ]] [[ಸುಗ್ಗಿ ಬೇಸಾಯೊ]],[[ಕುದುರೆ ಕೋಲ]]/ನಾಗ ಬೆರ್ಮನ ಕೋಲ, [[ಪರ್ಬೊ|ಕೊಡಿ ಪರ್ಬೊ]] || ಬೊಂತೆಲ್ ಸುಗ್ಗಿಗ್ ಬಿತ್ತೊನುಲ ಗೊಂತುದ ಪರ್ಬೊನು ಮಲ್ತೊನುಲ || ಬೊಂತೆಲ್ದ ಅಮಾಸೆಗ್ ಕೊಡಿಪರ್ಬೊ ಮಲ್ಪುವೆರ್ |- | ೦೮ || [[ಜಾರ್ತೆ]]/ಜಾರ್ದೆ<ref>{{cite book |last1=Upadhyaya |first1=Uliyar Padmanabha|author-link=ಉಳಿಯಾರ್ ಪದ್ಮನಾಭ ಉಪಾಧ್ಯಾಯ |title=Tuḷu nighaṇṭu: Tuḷu-kannaḍa-iṅgliś śabdakōśa |date=1997 |publisher=Rāṣṭrakavi Gōvinda Pai saṃśōdhana kendra |location=Udupi (Bhārata) |pages=1317 |edition=Fiirst|url=https://tuludictionary.in/dictionary/cgi-bin/web/frame.html}}</ref>, ವೃಶ್ಚಿಕ ಮಾಸ || [[ಕಾವೇರಿ ಪುರ್ಸೆ]], ಹರಿಸೇವೆ [[ಹೌಂಡೇ ರಾಯ್ನ ವಾಲ್ಗ]] ಜಾರ್ತೆದ [[ಪುಣ್ಣಮೆ]] || ಜಾರ್ದೆಡ್ ಕೊಡಿ ಮುಲಿ ಕೊಂಡಲ್ಲ ಏರ್ದಿನ ನಿನ ಬಯಿ ನಮೋತೊನುಲ || ಜಾರ್ದೆ ಪುಣ್ಣಮೆಗೆಂಕ್ಲೆನಿಲ್ಲ ಕಯ್ತಲ್ ಬಾರಿ ಗೌಜಿಡಾಪಿನ ನೇಮ |- | ೦೯ || [[ಪೆರಾರ್ದೆ]]/ಪೆರಾರ್ತೆ, ಧನುಮಾಸ || || || |- | ೧೦ || [[ಪೊನ್ನಿ]]/ಪುನಿಯಿ ಮಕರ ಮಾಸ || [[ಕೆಡ್ಡಸ]], [[ಮಕರ ಸಂಕ್ರಾಂತಿ]], [[ಪಾಣಾರಾಟ|ಪಾಣಾರಾಟೊ]] || || |- | ೧೧ || [[ಮಾಯಿ]]/ಮಾಕಿ - ಕುಂಭಮಾಸ<ref>{{cite book |last1=Upadhyaya |first1=Uliyar Padmanabha |title=Tuḷu nighaṇṭu: Tuḷu-kannaḍa-iṅgliś śabdakōśa |date=1997|publisher=Rāṣṭrakavi Gōvinda Pai saṃśōdhana kendra |location=Udupi (Bhārata) |isbn=81-86668-20-9|pages= 2567}}</ref> || [[ಕಂಗೀಲು]], [[ಮಾಯಿದ ಪುರ್ಸೆರ್]], ಮಾಯಿದ ನಡಾವಳಿ || ಮಾಯಿಡ್ದ್ ಬುಕ್ಕೊ ಮರಿಯಾಲೊ, ಆಟಿಡ್ದ್ ಬುಕ್ಕೊ ಅರೆಗಾಲೊ || ಮಾಯಿಡ್ ಬರ್ಸ ಬತ್ತ್ಂಡ ಮಲೆ ಬುಲೆವು |- | ೧೨ || [[ಸುಗ್ಗಿ]]/ಮೀನ ಮಾಸ<ref>{{cite book |last1=Upadhyaya |first1=Uliyar Padmanabha|author-link=ಉಳಿಯಾರ್ ಪದ್ಮನಾಭ ಉಪಾಧ್ಯಾಯ |title=Tuḷu nighaṇṭu: Tuḷu-kannaḍa-iṅgliś śabdakōśa |date=1997 |publisher=Rāṣṭrakavi Gōvinda Pai saṃśōdhana kendra |location=Udupi (Bhārata) |isbn=81-86668-20-9 |pages=2952 |edition=Fiirst|url=https://tuludictionary.in/dictionary/cgi-bin/web/frame.html}}</ref> || [[ಒತ್ತೆಕೋಲ|ವಿಷ್ಣುಮೂರ್ತಿ ಕೋಲ]], [[ಸುಗ್ಗಿದ ನಲಿಕೆ|ಸುಗ್ಗಿ ನಲಿಕೆ]] [[ಕರ್ಂಗೋಲು]], [[ಪಿಲಿಪಂಜಿ ನಲಿಕೆ]], [[ಸಿರಿ]] ಆರಾದನೆ<ref>{{cite book |last1=Rāmakr̥ṣṇa Ācār |first1=Pāltāḍi |title=Tuḷunāḍina janapada pradarśana kalegaḷu |date=2017 |publisher=Vistaraṇe hāgu Salahā Kēndra, Karnāṭaka Janapada Viśvavidyālaya |location=Goṭagōḍi, Śiggāvi Tā., Hāvēri Jille |isbn=978-93-83149-54-4 |pages=162 |edition=First}}</ref> [[ಗೋಂದೊಲು ಪೂಜೆ]], [[ಕೊರಗತನಿಯೆ|ಕೊರಗ-ತನಿಯ ನಲಿಕೆ]]|| ಏಣೆಲ್ ಬೆನ್ನಿ ಬೆಂದಿನಾಯಡ ಸುಗ್ಗಿಗ್ ಬಿತ್ತ್ ಕೇಂಡಿಲೆಕೊ || ಮಾರುನ ಮುಂಬುನು ಸುಗ್ಗಿಪಗ್ಗುಡ್ ಮಾರ್ಂಡ್(ಮಾರುವ ದನಕರುವನ್ನು ಮೀನಮೇಷ ಮಾಸಗಳಲ್ಲೇ ಮಾರಿಯಾಯಿತು |} == ರಾಷ್ಟ್ರೀಯ ಕಾಲಮಾನೊದ ವಿವರೊ == {| class="wikitable" |- ! ಕ್ರಮ ಸಂಕ್ಯೆ !! ರುತು !! ತಿಂಗೊಲುಲು |- | 01|| ವಸಂತ || ಚೈತ್ರಾ-ವೈಶಾಖ |- | 02|| ಗ್ರೀಷ್ಮ || ಜೇಷ್ಠ-ಆಶಾಡ |- | 03|| ವರ್ಷ || ಶ್ರಾವಣ-ಭಾದ್ರಪದ |- | 04|| ಶರತ್ || ಅಶ್ವಯುಜ-ಕಾರ್ತೀಕ |- | 05|| ಹೇಮಂತ || ಮಾರ್ಗಶಿರ-ಪುಷ್ಯ |- | 06|| ಶಿಶಿರ || ಮಾಘ-ಪಾಲ್ಗುಣ |} == ಬುಲೆ ಬುಕ್ಕೊ ಕಾಲೊ == ತುಳುವೆರೆನ ಬೆನ್ನಿ ಬೇಸಾಯೊಡು [[ಮೂಜಿ]] ವಿದೊ. ಬೆನ್ನಿನ್ ಆಯಾ ತಿಂಗುಲುದ ಕಾಲೊದ ನೆಲೆಟ್ [[ಬಿತ್ತ್]] ಪಾಡ್ದ್ ಬುಲೆಪೆರ್. ಪಿರಾಕ್‍ಡ್ ಕಾಲೊಗು ತಕ್ಕಂದಿನ ಬಿದಿಕ್ಕುಲಿತ್ತೊ. ಪೊಸ ಕಾಲೊ ಬನ್ನಗ ಆ [[ಬಿದೆ]]ಕ್ಕುಲು ನಾಶ ಆತೊ. ಉದಾರ್ಮೆಗ್; [[ನೀರಂಬಟೆ]], [[ಕಯಮ್ಮೆ]]. {| class="wikitable" |- ! ಕ್ರಮ ಸಂಕ್ಯೆ !! ಬುಲೆ !! ತಿಂಗೊಲು !! ಕಾಲ |- | 01 || [[ಏನೆಲ್ ಬೇಸಾಯೊ]] || [[ಪಗ್ಗು]], [[ಬೇಸ|ಬೇಷ]], [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತಿಯೊಲ್]], [[ಆಟಿ]], [[ಸೋಣೊ]], [[ನಿರ್ನಾಲೊ]] || [[ಮರಿಯಾಲೊ]] |- | 02|| [[ಸುಗ್ಗಿ ಬೇಸಾಯೊ]] ||[[ಬೊಂತ್ಯೊಲು]], [[ಜಾರ್ತೆ]], [[ಪೆರಾರ್ದೆ]] || [[ಚಳಿಗಾಲೊ]] |- | 03|| [[ಕೊಳಕೆ ಬೇಸಾಯೊ]] || [[ಪೊನ್ನಿ]], [[ಮಾಯಿ]], [[ಸುಗ್ಗಿ]] || [[ಅರೆಗಾಲೊ]] |} ==ಪಿದಾಯಿದ ಕೊಂಡಿಲು== *https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/%3C/ == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ಜಾನಪದ]] ffhee5usq5ecn7fnb1h5mrv4udte9o2 ನರೇಂದ್ರ ಮೋದಿ 0 4389 360707 360630 2026-05-16T04:58:37Z Mahaveer Indra 1023 deleted unsupported template data 360707 wikitext text/x-wiki {{Infobox officeholder |name=ನರೇಂದ್ರ ಮೋದಿ <!-- DO NOT ADD INDIC SCRIPTS --> | image = The official portrait of Shri Narendra Modi, the Prime Minister of the Republic of India.jpg | caption =ಅಧಿಕೃತ ಭಾವಚಿತ್ರ, ೨೦೨೪ |office=ಭಾರತದ ೧೪ನೇ [[ಭಾರತದ ಪ್ರಧಾನ ಮಂತ್ರಿ|ಪ್ರಧಾನಮಂತ್ರಿ]] |president=[[ಪ್ರಣಬ್ ಮುಖರ್ಜಿ]] <br> [[ರಾಮ್ ನಾಥ್ ಕೋವಿಂದ್]]<br> [[ದ್ರೌಪದಿ ಮುರ್ಮು]] |term_start=೨೬ ನೇ ಮೇ ೨೦೧೪ |term_end= |predecessor=[[ಮನಮೋಹನ್ ಸಿಂಗ್]]|office1=ಭಾರತದ ಪ್ರಧಾನ ಮಂತ್ರಿ|governor1=ಸುಂದರ್ ಸಿಂಗ್ ಭಂಡಾರಿ<br>ಕೈಲಾಸಪತಿ ಮಿಶ್ರಾ<br>ಬಲರಾಮ್ ಜಾಖಡ್<br>ನವಲ್ ಕಿಶೋರ್ ಶರ್ಮ<br>ಎಸ್.ಸಿ.ಜಮೀರ್<br>ಕಮಲಾ ಬೆನಿವಾಲ್|term_start1=7 ಅಕ್ಟೋಬರ್ 2001|term_end1=22 May 2014|predecessor1=ಕೇಶುಭಾಯಿ ಪಟೇಲ್|successor1=ಆನಂದಿ ಬೆನ್ ಪಟೇಲ್|birthname=ನರೇಂದ್ರ ದಾಮೋದರದಾಸ ಮೋದಿ |birth_date={{birth date and age|1950|9|17|df=y}} |birth_place=ವಡನಗರ, ಮೆಹಸಾನಾ, [[ಗುಜರಾತ್]]|death_date=|death_place=|party=[[ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷ]]|alma_mater=ಗುಜರಾತ್ ವಿಶ್ವವಿದ್ಯಾಲಯ|website=[http://www.narendramodi.in Official website]|signature=Signature of Narendra Modi (Hindi).svg}} [[ಫೈಲ್:Narendramodi.jpg|right|thumb| ನರೇಂದ್ರ ಮೋದಿ]] '''ನರೇಂದ್ರ ದಾಮೋದರದಾಸ ಮೋದಿ''' (ಸೆಪ್ಟೆಂಬರ್ ೧೭, ೧೯೫೦) [[ಭಾರತ|ಭಾರತದ]] ೧೪ನೇ ಪ್ರಧಾನಿ.<ref>{{Cite news|url=https://www.bbc.com/news/world-asia-india-27514601|title=In pictures: Narendra Modi's early life|date=2014-05-25|work=BBC News|access-date=2025-10-23|language=en}}</ref> ಆರ್ ಭಾರತೀಯ ಜನತಾ ಪಾರ್ಟಿದ ಸದಸ್ಯೆರ್. [[ಗುಜರಾತ್]] ರಾಜ್ಯೊದ ದಿಂಜ ಸಮಯೊ ಸೇವೆ ಕೊರ್‌ನ ಮುಖ್ಯಮಂತ್ರಿ. ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷೊಡ್ದ್ (ಎನ್ ಡಿ ಎ ಮೈತ್ರಿ) 2014 ಲೋಕಸಭಾ ಚುನಾವಣೆಡ್ ಸ್ಪರ್ದೆಡ್ ಗೆಂದಿಯೆರ್ ಬುಕ್ಕೊ ಭಾರತೊದ 14ನೇ ಪ್ರಧಾನಿ ಆಯೆರ್. ಮೋದಿ ವಾರಾಣಸಿಡ್ದ್ ಇತ್ತೆದ ಸಂಸದೆರ್, ಗುಜರಾತ್‌ಡ್ ವಡೋದರ, ಬುಕ್ಕೊ ವಾರಾಣಸಿ ಕ್ಷೇತ್ರೊಲೆನ್ ಗೆಂದಿಯೆರ್. == ಬಾಲ್ಯೊ == [[ಗುಜರಾತ್]] ರಾಜ್ಯೊದ ಮೆಹ್ಸಾನಾ ಜಿಲ್ಲೆದ ವಡನಗರ <ref>{{Cite web|title=Narendra Damodardas Modi :Early days in Politics, Criticisms,and Awards|url=https://www.mapsofindia.com/who-is-who/government-politics/narendra-modi.html|website=Who-is-who|date=2018-02-03|accessdate=2025-10-23|language=en|last=geeta}}</ref> ದ ಮೋದಿ ಕುಟುಂಬೊಡು ೪ ಜೋಕುಲೆಡ್ ಮೂಜಿನೆ ಮಗೆ ಆಯಿನ ತೆಲಿ ಜಾತಿದ ಬಾರಿ ಬಡ ಕುಟುಂಬೊಡು ೧೯೫೦ ಸೆಪ್ಟೆಂಬರ್ ೧೭ ತಾರೀಕ್‌ಗ್ ಮೋಧ್ ಗಂಛಿ ಪುಟ್ಟುವೆರ್. ಅಮ್ಮೆರ್ ದಾಮೋದರ ದಾಸ್ ಮುಲಚಂದ್ ಮೋದಿ ಬುಕ್ಕೊ ಅಪ್ಪೆ ಹೀರಾ ಬೆನ್. ಮೋದಿ ವಾಡ್ ನಗರ ರೈಲ್ವೆ ನಿಲ್ದಾಣೊಡು ಚಾಯೊ ಸ್ಟಾಲ್ ನಡಪಾವೊಂದು ಅಮ್ಮಗ್ ಸಹಾಯೊ ಮಲ್ತೊಂದಿತ್ತೆರ್.<ref>{{Cite web|title=Narendra Modi when six-year-old sold tea at Vadnagar station, says a new book|url=https://www.indiatoday.in/india/west/story/narendra-modi-sold-tea-at-vadnagar-station-says-new-book-168568-2013-06-29|website=India Today|date=2013-06-30|accessdate=2025-10-23|language=en|last=IANS}}</ref> ಅಜಿಪನೆ ದಶಕೊದ ನಡುಬಾಗೊಡು ಇಂಡೋ-ಪಾಕ್ ಯುದ್ಧೊದ ಪೊರ್ತುಡು, ಬಾಲೆ ಮೋದಿ ರೈಲ್ವೆ ನಿಲ್ದಾಣೊಲೆಡ್ ಸೈನಿಕೆರಾದ್ ಸೇವೆ ಮಲ್ಪೆರೆ ಸ್ವಯಂಪ್ರೇರಿತವಾದ್ ಬತ್ತೆರ್. ಆರ್ 1967ಡ್ ಗುಜರಾತ್ ದ ಪ್ರವಾಹ ಬಾದೆಗ್ ತಿಕ್ಕಿನ ಜನಕುಲೆನ ಸೇವೆ ಮಲ್ತೆರ್. ಅಖಿಲ ಭಾರತೀಯ ವಿದ್ಯಾರ್ಥಿ ಪರಿಷತ್ (ಎಬಿವಿಪಿ) ದ ಮುಖಂಡರಾದ್ ಆಯ್ಕೆ ಆಯೆರ್. ಗುಜರಾತ್ಡ್ ಮಸ್ತ್ ಸಾಮಾಜಿಕ-ರಾಜಕೀಯ ಚಳುವಳಿಲೆಡ್ ಸಕ್ರಿಯವಾದ್ ಪಾಲ್ ಪಡೆಯೆರ್. == ಮದ್ಮೆ == 13 ವರ್ಸೊ ಪ್ರಾಯೊಡು ಮೋದಿ ಜಶೋದಾ ಬೆನ್ ಚಿಮಾನ್ ಲಾಲ್ ನೊಟ್ಟುಗು ಮದ್ಮೆದ ನಿಚ್ಚಯೊ ಮಲ್ತೆರ್. ಮದಿಮೆ 18ನೆ ವರ್ಸಡ್ ನಡತ್ಂಡ್. ಬಾಲ್ಯೊ ಜೋಡಿ ಜೊತೆಟ್ ಪೋಯೆರ್, ಬುಕ್ಕೊ ಅರ್ ಬುಡೆದಿನ್ ಬುಡ್ದ್ ಪೋಯೆರ್. ಜಶೋದಾಬೆನ್ ಆರೆನ ಇಡೀ ಜೀವನೊನು ಒರಿ ಶಿಕ್ಷಕಿಯಾದ್ ಕಳೆಯೆರ್ ಬುಕ್ಕೊ ಇತ್ತೆ ನಿವೃತ್ತೆರ್. == ಆರ್ ಎಸ್ ಎಸ್ ದ ಸಂಪರ್ಕೊ == ಆರ್ ರಾಷ್ಟ್ರೀಯ ಸ್ವಯಂಸೇವಕ ಸಂಘೊಗು ಸೇರ್ದ್ ಬಾರೀ ಕ್ರಿಯಾಶೀಲವಾದ್ ಬೇಲೆ ಮಲ್ತೆರ್. ಭಾರತೊದ ಇತಿಹಾಸೊನು ಅಬ್ಯಾಸೊ ಮಲ್ಪುಲೆ ಬುಕ್ಕೊ ಪ್ರಾಚೀನ, ಮಧ್ಯಕಾಲೀನ ಬುಕ್ಕೊ ಆಧುನಿಕ ಭಾರತೊದ ಬಗ್ಗೆ ತೆರಿಯೊನೊಲಿ. [[ಇಂದಿರಾ ಗಾಂಧಿ|ಇಂದಿರಾ]] ಗಾಂಧಿ 1975ಡ್ ತುರ್ತು ಪರಿಸ್ಥಿತಿನ್ ಘೋಷಣೆ ಮಲ್ಪುನಗ, ಅವೆನ್ ವಿರೋಧ ಮಲ್ತ್‌ದ್ ಅರೆನ ಸ್ವಂತ ಕೊಡುಗೆನ್ ಕೊರ್ತೆರ್. ಅಖಿಲ ಭಾರತೀಯ ವಿದ್ಯಾರ್ಥಿ ಪರಿಷತ್ (ಎಬಿವಿಪಿ)ದ ಮುಖಂಡೆರಾದ್ ಸೇವೆ ಸಂದಾದೆರ್. == ಕಲ್ಪಾಟಿಗೆ == * ಉನ್ನತ ಶಿಕ್ಷಣೊಗು ಕಾಲೇಜ್ ಬುಕ್ಕೊ ವಿಶ್ವವಿದ್ಯಾಲಯೊಗು ಸೇರ್ನಗ ಮೋದಿ ನಾನಾತ್ ಕಸ್ಟೊದ ಮಾರ್ಗೊಡು ನಡತೆರ್. * ಆರ್ ರಾಜಕೀಯ ವಿಜ್ಞಾನೊಡು ಸ್ನಾತಕೋತ್ತರ ಪದವಿ ಪಡೆಯೆರ್. ಭಾರತೊದ ಸಾಮಾಜಿಕ, ಸಾಂಸ್ಕೃತಿಕ ಬುಲೆಚಿಲ್‍ನ್ ಮನಸ್ಸ್‌ಡ್ ದೀಡ್ದ್ ರಾಷ್ಟ್ರೀಯ ಸ್ವಯಂ ಸೇವಕ ಸಂಘದೊಟ್ಟಿಗೆ ಆರೆನ ಸಮ್ಮಂದೊನು ಸುರು ಮಲ್ತೆರ್. ಆರ್ ಎಸ್ ಎಸ್ ಡ್ ಇಪ್ಪುನಗ, ಮೋದಿ ಕೆಲವು ಮಲ್ಲ ಕೆಲಸೊಲೆನ್ ಮಲ್ತೆರ್. * ಮೋದಿ ವ್ಯವಸ್ತೆದ ಉಳಿಕೆ ಭಾಗೊಲು ಕೇಂದ್ರ ಸರ್ಕಾರದ ಸರ್ವಾಧಿಕಾರಿ ಮನೋಭಾವೊಗು ವಿರುದ್ಧವಾದ್ ಪ್ರತಿಭಟನೆ ಮಲ್ತ್‌ದ್, 1974 ನವನಿರ್ಮಾನ್ ಭ್ರಷ್ಟಾಚಾರ ವಿರೋಧಿ ಚಳುವಳಿಡ್ ಬುಕ್ಕೊ 19 ತಿಂಗೊಲುದ (ಜೂನ್ 1975 ಡ್ದ್ ಜನವರಿ 1977 ಮುಟ್ಟ) ತುರ್ತು ಪರಿಸ್ಥಿತಿನ್ ಜಾರಿ ಮಲ್ತ್‌ದ್ ನಾಗರಿಕೆರೆಗ್ ಅಕ್ಲೆನ ಮೂಲಭೂತ ಹಕ್ಕುಲೆನ್ ತೆರಿಪಾವೊಂದಿತ್ತೆರ್. == ರಾಜಕೀಯೊ == === ಭಾರತೊದ ಪ್ರಧಾನ ಮಂತ್ರಿಯಾದ್ ಮೋದಿ === [[ಫೈಲ್:The_President,_Shri_Ram_Nath_Kovind_administering_the_oath_of_office_of_the_Prime_Minister_to_Shri_Narendra_Modi,_at_a_Swearing-in_Ceremony,_at_Rashtrapati_Bhavan,_in_New_Delhi_on_May_30,_2019_(3).jpg|thumb|239x239px| ನರೇಂದ್ರ ಮೋದಿ ರಡ್ಡನೆ ಸರ್ತಿ ಭಾರತದ ಪ್ರಧಾನಿಯಾದ್ ಪ್ರಮಾಣ ವಚನ ದೆತೊನುವೆರ್, ಅಧ್ಯಕ್ಷೆರ್ ರಾಮನಾಥ್ ಕೋವಿಂದ್ ಪ್ರಮಾಣ ವಚನ ಮಲ್ತೆರ್.]] == ಪ್ರಶಸ್ತಿ/ಗೌರವೊ == * ರಷ್ಯಾ ಸರ್ಕಾರ ಪ್ರಧಾನಿ ನರೇಂದ್ರ ಮೋದಿಗ್ 'ಆರ್ಡರ್ ಆಫ್ ಅಪೊಸ್ತೊಲಿಕ್ ಸೈಂಟ್ ಆಂಡ್ರ್ಯೂ' ನ್ ಗೌರವಿಸಾಯಿನವು. - ಏಪ್ರಿಲ್ ೧೨, ೨೦೧೯ <ref>{{Cite web|title=Russia awards Narendra Modi its highest order, PM thanks Putin|url=https://www.indiatoday.in/india/story/russia-narendra-modi-order-of-st-andrew-the-apostle-1500321-2019-04-12|website=India Today|date=2019-04-12|accessdate=2025-10-23|language=en|first=India Today Web|last=Desk}}</ref> * ಯುನೈಟೆಡ್ ಅರಬ್ ಎಮಿರೇಟ್ಸ್ (ಯುಎಇ) ಪ್ರಧಾನಿ ನರೇಂದ್ರ ಮೋದಿನ್ ಜಾಯೆದ್ ಪದಕೊಡು ಗೌರವಿಸವುಂಡು - ಏಪ್ರಿಲ್ ೪, ೨೦೧೯ <ref>{{Cite web|title=UAE confers highest civil honour on Indian PM Modi for giving bilateral ties 'a big boost'|url=https://www.dawn.com/news/1473880|website=Dawn|date=2019-04-04|accessdate=2025-10-23|language=en|last=Dawn.com}}</ref> * ನರೇಂದ್ರ ಮೋದಿಗ್ ಫಿಲಿಪ್ ಕೊಟ್ಲರ್ ಅಧ್ಯಕ್ಷೀಯ ಪ್ರಶಸ್ತಿ - ಜನವರಿ ೧೪, ೨೦೧೯ <ref>{{Cite news|url=https://m.timesofindia.com/india/pm-modi-receives-philip-kotler-award/articleshow/67525994.cms|title=PM Modi receives Philip Kotler award|date=2019-01-14|work=The Times of India|access-date=2025-10-23}}</ref> * ನರೇಂದ್ರ ಮೋದಿಗ್ "ಮೋಡಿನೊಮಿಕ್ಸ್" ಗ್ ಪ್ರತಿಷ್ಠಿತ ಸಿಯೋಲ್ ಪ್ರಶಸ್ತಿ 2018 - ಅಕ್ಟೋಬರ್ 24, 2018 <ref>{{Cite web|title=PM Modi awarded for Modinomics: All you need to know about the Seoul Peace Prize|url=https://www.indiatoday.in/fyi/story/modi-award-modinomics-seoul-peace-prize-seoul-1462266-2019-02-22|website=India Today|date=2019-02-22|accessdate=2025-10-23|language=en|first=India Today Web|last=Desk}}</ref> * ಪ್ರಧಾನಿ ಮೋದಿಗ್ ವಿಶ್ವ ಸಂಸ್ಥೆದ ಚಾಂಪಿಯನ್ಸ್ ಆಫ್ ದ ಅರ್ಥ್ ಪ್ರಶಸ್ತಿ 2018 - ಸೆಪ್ಟೆಂಬರ್ 26, 2018 * ಪ್ರಧಾನಿ ಮೋದಿ ಪ್ಯಾಲೆಸ್ಟೈನ್ ರಾಜ್ಯದ ಗ್ರ್ಯಾಂಡ್ ಕಾಲರ್ ನ್ ಪ್ರಶಸ್ತಿ ಮಲ್ತೆರ್ - ಫೆಬ್ರವರಿ ೧೦, ೨೦೧೮ <ref>{{Cite news|url=https://www.thehindu.com/news/national/modi-conferred-grand-collar-of-the-state-of-palestine/article22714293.ece|title=Modi conferred ‘Grand Collar of the State of Palestine’|last=PTI|date=2018-02-10|work=The Hindu|access-date=2025-10-23|language=en-IN}}</ref> * ಪ್ರಧಾನಿ ನರೇಂದ್ರ ಮೋದಿ ಅಫ್ಘಾನಿಸ್ತಾನದ ಅಮೀರ್ ಅಬ್ದುಲ್ಲಾ ಖಾನ್ ಪ್ರಶಸ್ತಿನ್ ಕೊರ್ತೆರ್ - ಜೂನ್ ೪, ೨೦೧೬ <ref>https://www.narendramodi.in/pm-modi-presented-with-amir-amanullah-khan-award-afghanistan-s-highest-civilian-honour--484015</ref> * ಮೋದಿ ಸೌದಿ ಅರೇಬಿಯಾದ ರಾಜ ಅಬ್ದುಲಾಜೀಜ್ ಸ್ಯಾಶ್ ಪ್ರಶಸ್ತಿನ್ ಕೊರ್ತೆರ್ - ಏಪ್ರಿಲ್ ೩, ೨೦೧೬ <ref>{{Cite web|title=PM Modi conferred Saudi’s highest civilian honour|url=https://indianexpress.com/article/india/india-news-india/modi-saudi-arabia-king-abdulaziz-sash-civilian-honour/|website=The Indian Express|date=2016-04-03|accessdate=2025-10-23|language=en}}</ref> [[ಫೈಲ್:Prime Minister Narendra Modi with his mother.jpg|thumb|ಪ್ರಧಾನಿ ಮೋದಿ ಅರೆನ ಅಪ್ಪೆನೊಟ್ಟುಗು]] * ಉಡುಪಿಡ್ ಪರ್ಯಾಯ ಶ್ರೀ ಪುತ್ತಿಗೆ ಮಠದ ಶ್ರೀ ಸುಗುಣೇಂದ್ರ ತೀರ್ಥ ಸ್ವಾಮೀಜಿಯೆರ್ ನವೆಂಬರ್ ೨೮, ೨೦೨೫ ಶುಕ್ರವಾರದಾನಿ ನರೇಂದ್ರ ಮೋದಿಗ್ 'ಭಾರತ ಭಾಗ್ಯ ವಿಧಾತ' ಪನ್ಪಿ ಬಿರುದು ಕೊರ್ದು ಮಾನಾದಿಗೆ ಮಲ್ತೆರ್.<ref> https://www.newindianexpress.com/states/karnataka/2025/Nov/29/puthige-seer-calls-pm-modi-bharata-bhagya-vidhata-seeks-udupi-corridor</ref> == ತೂಲೆ == * ಭಾರತದ ಪ್ರಧಾನ ಮಂತ್ರಿ * ಭಾರತದ ಸಚಿವ ಪರಿಷತ್ ೨೦೧೪ == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ಪ್ರಧಾನ ಮಂತ್ರಿ]] [[ವರ್ಗೊ:ಮುಖ್ಯಮಂತ್ರಿ]] ov2gx7i02gy8qpbcf3l8a4l68mn4biz 360708 360707 2026-05-16T05:08:20Z Mahaveer Indra 1023 citation link edited 360708 wikitext text/x-wiki {{Infobox officeholder |name=ನರೇಂದ್ರ ಮೋದಿ <!-- DO NOT ADD INDIC SCRIPTS --> | image = The official portrait of Shri Narendra Modi, the Prime Minister of the Republic of India.jpg | caption =ಅಧಿಕೃತ ಭಾವಚಿತ್ರ, ೨೦೨೪ |office=ಭಾರತದ ೧೪ನೇ [[ಭಾರತದ ಪ್ರಧಾನ ಮಂತ್ರಿ|ಪ್ರಧಾನಮಂತ್ರಿ]] |president=[[ಪ್ರಣಬ್ ಮುಖರ್ಜಿ]] <br> [[ರಾಮ್ ನಾಥ್ ಕೋವಿಂದ್]]<br> [[ದ್ರೌಪದಿ ಮುರ್ಮು]] |term_start=೨೬ ನೇ ಮೇ ೨೦೧೪ |term_end= |predecessor=[[ಮನಮೋಹನ್ ಸಿಂಗ್]]|office1=ಭಾರತದ ಪ್ರಧಾನ ಮಂತ್ರಿ|governor1=ಸುಂದರ್ ಸಿಂಗ್ ಭಂಡಾರಿ<br>ಕೈಲಾಸಪತಿ ಮಿಶ್ರಾ<br>ಬಲರಾಮ್ ಜಾಖಡ್<br>ನವಲ್ ಕಿಶೋರ್ ಶರ್ಮ<br>ಎಸ್.ಸಿ.ಜಮೀರ್<br>ಕಮಲಾ ಬೆನಿವಾಲ್|term_start1=7 ಅಕ್ಟೋಬರ್ 2001|term_end1=22 May 2014|predecessor1=ಕೇಶುಭಾಯಿ ಪಟೇಲ್|successor1=ಆನಂದಿ ಬೆನ್ ಪಟೇಲ್|birthname=ನರೇಂದ್ರ ದಾಮೋದರದಾಸ ಮೋದಿ |birth_date={{birth date and age|1950|9|17|df=y}} |birth_place=ವಡನಗರ, ಮೆಹಸಾನಾ, [[ಗುಜರಾತ್]]|death_date=|death_place=|party=[[ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷ]]|alma_mater=ಗುಜರಾತ್ ವಿಶ್ವವಿದ್ಯಾಲಯ|website=[http://www.narendramodi.in Official website]|signature=Signature of Narendra Modi (Hindi).svg}} [[ಫೈಲ್:Narendramodi.jpg|right|thumb| ನರೇಂದ್ರ ಮೋದಿ]] '''ನರೇಂದ್ರ ದಾಮೋದರದಾಸ ಮೋದಿ''' (ಸೆಪ್ಟೆಂಬರ್ ೧೭, ೧೯೫೦) [[ಭಾರತ|ಭಾರತದ]] ೧೪ನೇ ಪ್ರಧಾನಿ.<ref>{{Cite news|url=https://www.bbc.com/news/world-asia-india-27514601|title=In pictures: Narendra Modi's early life|date=2014-05-25|work=BBC News|access-date=2025-10-23|language=en}}</ref> ಆರ್ ಭಾರತೀಯ ಜನತಾ ಪಾರ್ಟಿದ ಸದಸ್ಯೆರ್. [[ಗುಜರಾತ್]] ರಾಜ್ಯೊದ ದಿಂಜ ಸಮಯೊ ಸೇವೆ ಕೊರ್‌ನ ಮುಖ್ಯಮಂತ್ರಿ. ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷೊಡ್ದ್ (ಎನ್ ಡಿ ಎ ಮೈತ್ರಿ) 2014 ಲೋಕಸಭಾ ಚುನಾವಣೆಡ್ ಸ್ಪರ್ದೆಡ್ ಗೆಂದಿಯೆರ್ ಬುಕ್ಕೊ ಭಾರತೊದ 14ನೇ ಪ್ರಧಾನಿ ಆಯೆರ್. ಮೋದಿ ವಾರಾಣಸಿಡ್ದ್ ಇತ್ತೆದ ಸಂಸದೆರ್, ಗುಜರಾತ್‌ಡ್ ವಡೋದರ, ಬುಕ್ಕೊ ವಾರಾಣಸಿ ಕ್ಷೇತ್ರೊಲೆನ್ ಗೆಂದಿಯೆರ್. == ಬಾಲ್ಯೊ == [[ಗುಜರಾತ್]] ರಾಜ್ಯೊದ ಮೆಹ್ಸಾನಾ ಜಿಲ್ಲೆದ ವಡನಗರ <ref>{{Cite web|title=Narendra Damodardas Modi :Early days in Politics, Criticisms,and Awards|url=https://www.mapsofindia.com/who-is-who/government-politics/narendra-modi.html|website=Who-is-who|date=2018-02-03|accessdate=2025-10-23|language=en|last=geeta}}</ref> ದ ಮೋದಿ ಕುಟುಂಬೊಡು ೪ ಜೋಕುಲೆಡ್ ಮೂಜಿನೆ ಮಗೆ ಆಯಿನ ತೆಲಿ ಜಾತಿದ ಬಾರಿ ಬಡ ಕುಟುಂಬೊಡು ೧೯೫೦ ಸೆಪ್ಟೆಂಬರ್ ೧೭ ತಾರೀಕ್‌ಗ್ ಮೋಧ್ ಗಂಛಿ ಪುಟ್ಟುವೆರ್. ಅಮ್ಮೆರ್ ದಾಮೋದರ ದಾಸ್ ಮುಲಚಂದ್ ಮೋದಿ ಬುಕ್ಕೊ ಅಪ್ಪೆ ಹೀರಾ ಬೆನ್. ಮೋದಿ ವಾಡ್ ನಗರ ರೈಲ್ವೆ ನಿಲ್ದಾಣೊಡು ಚಾಯೊ ಸ್ಟಾಲ್ ನಡಪಾವೊಂದು ಅಮ್ಮಗ್ ಸಹಾಯೊ ಮಲ್ತೊಂದಿತ್ತೆರ್.<ref>{{Cite web|title=Narendra Modi when six-year-old sold tea at Vadnagar station, says a new book|url=https://www.indiatoday.in/india/west/story/narendra-modi-sold-tea-at-vadnagar-station-says-new-book-168568-2013-06-29|website=India Today|date=2013-06-30|accessdate=2025-10-23|language=en|last=IANS}}</ref> ಅಜಿಪನೆ ದಶಕೊದ ನಡುಬಾಗೊಡು ಇಂಡೋ-ಪಾಕ್ ಯುದ್ಧೊದ ಪೊರ್ತುಡು, ಬಾಲೆ ಮೋದಿ ರೈಲ್ವೆ ನಿಲ್ದಾಣೊಲೆಡ್ ಸೈನಿಕೆರಾದ್ ಸೇವೆ ಮಲ್ಪೆರೆ ಸ್ವಯಂಪ್ರೇರಿತವಾದ್ ಬತ್ತೆರ್. ಆರ್ 1967ಡ್ ಗುಜರಾತ್ ದ ಪ್ರವಾಹ ಬಾದೆಗ್ ತಿಕ್ಕಿನ ಜನಕುಲೆನ ಸೇವೆ ಮಲ್ತೆರ್. ಅಖಿಲ ಭಾರತೀಯ ವಿದ್ಯಾರ್ಥಿ ಪರಿಷತ್ (ಎಬಿವಿಪಿ) ದ ಮುಖಂಡರಾದ್ ಆಯ್ಕೆ ಆಯೆರ್. ಗುಜರಾತ್ಡ್ ಮಸ್ತ್ ಸಾಮಾಜಿಕ-ರಾಜಕೀಯ ಚಳುವಳಿಲೆಡ್ ಸಕ್ರಿಯವಾದ್ ಪಾಲ್ ಪಡೆಯೆರ್. == ಮದ್ಮೆ == 13 ವರ್ಸೊ ಪ್ರಾಯೊಡು ಮೋದಿ ಜಶೋದಾ ಬೆನ್ ಚಿಮಾನ್ ಲಾಲ್ ನೊಟ್ಟುಗು ಮದ್ಮೆದ ನಿಚ್ಚಯೊ ಮಲ್ತೆರ್. ಮದಿಮೆ 18ನೆ ವರ್ಸಡ್ ನಡತ್ಂಡ್. ಬಾಲ್ಯೊ ಜೋಡಿ ಜೊತೆಟ್ ಪೋಯೆರ್, ಬುಕ್ಕೊ ಅರ್ ಬುಡೆದಿನ್ ಬುಡ್ದ್ ಪೋಯೆರ್. ಜಶೋದಾಬೆನ್ ಆರೆನ ಇಡೀ ಜೀವನೊನು ಒರಿ ಶಿಕ್ಷಕಿಯಾದ್ ಕಳೆಯೆರ್ ಬುಕ್ಕೊ ಇತ್ತೆ ನಿವೃತ್ತೆರ್. == ಆರ್ ಎಸ್ ಎಸ್ ದ ಸಂಪರ್ಕೊ == ಆರ್ ರಾಷ್ಟ್ರೀಯ ಸ್ವಯಂಸೇವಕ ಸಂಘೊಗು ಸೇರ್ದ್ ಬಾರೀ ಕ್ರಿಯಾಶೀಲವಾದ್ ಬೇಲೆ ಮಲ್ತೆರ್. ಭಾರತೊದ ಇತಿಹಾಸೊನು ಅಬ್ಯಾಸೊ ಮಲ್ಪುಲೆ ಬುಕ್ಕೊ ಪ್ರಾಚೀನ, ಮಧ್ಯಕಾಲೀನ ಬುಕ್ಕೊ ಆಧುನಿಕ ಭಾರತೊದ ಬಗ್ಗೆ ತೆರಿಯೊನೊಲಿ. [[ಇಂದಿರಾ ಗಾಂಧಿ|ಇಂದಿರಾ]] ಗಾಂಧಿ 1975ಡ್ ತುರ್ತು ಪರಿಸ್ಥಿತಿನ್ ಘೋಷಣೆ ಮಲ್ಪುನಗ, ಅವೆನ್ ವಿರೋಧ ಮಲ್ತ್‌ದ್ ಅರೆನ ಸ್ವಂತ ಕೊಡುಗೆನ್ ಕೊರ್ತೆರ್. ಅಖಿಲ ಭಾರತೀಯ ವಿದ್ಯಾರ್ಥಿ ಪರಿಷತ್ (ಎಬಿವಿಪಿ)ದ ಮುಖಂಡೆರಾದ್ ಸೇವೆ ಸಂದಾದೆರ್. == ಕಲ್ಪಾಟಿಗೆ == * ಉನ್ನತ ಶಿಕ್ಷಣೊಗು ಕಾಲೇಜ್ ಬುಕ್ಕೊ ವಿಶ್ವವಿದ್ಯಾಲಯೊಗು ಸೇರ್ನಗ ಮೋದಿ ನಾನಾತ್ ಕಸ್ಟೊದ ಮಾರ್ಗೊಡು ನಡತೆರ್. * ಆರ್ ರಾಜಕೀಯ ವಿಜ್ಞಾನೊಡು ಸ್ನಾತಕೋತ್ತರ ಪದವಿ ಪಡೆಯೆರ್. ಭಾರತೊದ ಸಾಮಾಜಿಕ, ಸಾಂಸ್ಕೃತಿಕ ಬುಲೆಚಿಲ್‍ನ್ ಮನಸ್ಸ್‌ಡ್ ದೀಡ್ದ್ ರಾಷ್ಟ್ರೀಯ ಸ್ವಯಂ ಸೇವಕ ಸಂಘದೊಟ್ಟಿಗೆ ಆರೆನ ಸಮ್ಮಂದೊನು ಸುರು ಮಲ್ತೆರ್. ಆರ್ ಎಸ್ ಎಸ್ ಡ್ ಇಪ್ಪುನಗ, ಮೋದಿ ಕೆಲವು ಮಲ್ಲ ಕೆಲಸೊಲೆನ್ ಮಲ್ತೆರ್. * ಮೋದಿ ವ್ಯವಸ್ತೆದ ಉಳಿಕೆ ಭಾಗೊಲು ಕೇಂದ್ರ ಸರ್ಕಾರದ ಸರ್ವಾಧಿಕಾರಿ ಮನೋಭಾವೊಗು ವಿರುದ್ಧವಾದ್ ಪ್ರತಿಭಟನೆ ಮಲ್ತ್‌ದ್, 1974 ನವನಿರ್ಮಾನ್ ಭ್ರಷ್ಟಾಚಾರ ವಿರೋಧಿ ಚಳುವಳಿಡ್ ಬುಕ್ಕೊ 19 ತಿಂಗೊಲುದ (ಜೂನ್ 1975 ಡ್ದ್ ಜನವರಿ 1977 ಮುಟ್ಟ) ತುರ್ತು ಪರಿಸ್ಥಿತಿನ್ ಜಾರಿ ಮಲ್ತ್‌ದ್ ನಾಗರಿಕೆರೆಗ್ ಅಕ್ಲೆನ ಮೂಲಭೂತ ಹಕ್ಕುಲೆನ್ ತೆರಿಪಾವೊಂದಿತ್ತೆರ್. == ರಾಜಕೀಯೊ == === ಭಾರತೊದ ಪ್ರಧಾನ ಮಂತ್ರಿಯಾದ್ ಮೋದಿ === [[ಫೈಲ್:The_President,_Shri_Ram_Nath_Kovind_administering_the_oath_of_office_of_the_Prime_Minister_to_Shri_Narendra_Modi,_at_a_Swearing-in_Ceremony,_at_Rashtrapati_Bhavan,_in_New_Delhi_on_May_30,_2019_(3).jpg|thumb|239x239px| ನರೇಂದ್ರ ಮೋದಿ ರಡ್ಡನೆ ಸರ್ತಿ ಭಾರತದ ಪ್ರಧಾನಿಯಾದ್ ಪ್ರಮಾಣ ವಚನ ದೆತೊನುವೆರ್, ಅಧ್ಯಕ್ಷೆರ್ ರಾಮನಾಥ್ ಕೋವಿಂದ್ ಪ್ರಮಾಣ ವಚನ ಮಲ್ತೆರ್.]] == ಪ್ರಶಸ್ತಿ/ಗೌರವೊ == * ರಷ್ಯಾ ಸರ್ಕಾರ ಪ್ರಧಾನಿ ನರೇಂದ್ರ ಮೋದಿಗ್ 'ಆರ್ಡರ್ ಆಫ್ ಅಪೊಸ್ತೊಲಿಕ್ ಸೈಂಟ್ ಆಂಡ್ರ್ಯೂ' ನ್ ಗೌರವಿಸಾಯಿನವು. - ಏಪ್ರಿಲ್ ೧೨, ೨೦೧೯<ref>{{cite web |title=Russia awards Narendra Modi its highest order, PM thanks Putin |url=https://www.indiatoday.in/india/story/russia-narendra-modi-order-of-st-andrew-the-apostle-1500321-2019-04-12 |website=indiatoday.in |publisher=India Today |access-date=16 May 2026}}</ref> * ಯುನೈಟೆಡ್ ಅರಬ್ ಎಮಿರೇಟ್ಸ್ (ಯುಎಇ) ಪ್ರಧಾನಿ ನರೇಂದ್ರ ಮೋದಿನ್ ಜಾಯೆದ್ ಪದಕೊಡು ಗೌರವಿಸವುಂಡು - ಏಪ್ರಿಲ್ ೪, ೨೦೧೯ <ref>{{Cite web|title=UAE confers highest civil honour on Indian PM Modi for giving bilateral ties 'a big boost'|url=https://www.dawn.com/news/1473880|website=Dawn|date=2019-04-04|accessdate=2025-10-23|language=en|last=Dawn.com}}</ref> * ನರೇಂದ್ರ ಮೋದಿಗ್ ಫಿಲಿಪ್ ಕೊಟ್ಲರ್ ಅಧ್ಯಕ್ಷೀಯ ಪ್ರಶಸ್ತಿ - ಜನವರಿ ೧೪, ೨೦೧೯ <ref>{{Cite news|url=https://m.timesofindia.com/india/pm-modi-receives-philip-kotler-award/articleshow/67525994.cms|title=PM Modi receives Philip Kotler award|date=2019-01-14|work=The Times of India|access-date=2025-10-23}}</ref> * ನರೇಂದ್ರ ಮೋದಿಗ್ "ಮೋಡಿನೊಮಿಕ್ಸ್" ಗ್ ಪ್ರತಿಷ್ಠಿತ ಸಿಯೋಲ್ ಪ್ರಶಸ್ತಿ 2018 - ಅಕ್ಟೋಬರ್ 24, 2018 <ref>{{Cite web|title=PM Modi awarded for Modinomics: All you need to know about the Seoul Peace Prize|url=https://www.indiatoday.in/fyi/story/modi-award-modinomics-seoul-peace-prize-seoul-1462266-2019-02-22|website=India Today|date=2019-02-22|accessdate=2025-10-23|language=en}}</ref> * ಪ್ರಧಾನಿ ಮೋದಿಗ್ ವಿಶ್ವ ಸಂಸ್ಥೆದ ಚಾಂಪಿಯನ್ಸ್ ಆಫ್ ದ ಅರ್ಥ್ ಪ್ರಶಸ್ತಿ 2018 - ಸೆಪ್ಟೆಂಬರ್ 26, 2018 * ಪ್ರಧಾನಿ ಮೋದಿ ಪ್ಯಾಲೆಸ್ಟೈನ್ ರಾಜ್ಯದ ಗ್ರ್ಯಾಂಡ್ ಕಾಲರ್ ನ್ ಪ್ರಶಸ್ತಿ ಮಲ್ತೆರ್ - ಫೆಬ್ರವರಿ ೧೦, ೨೦೧೮ <ref>{{Cite news|url=https://www.thehindu.com/news/national/modi-conferred-grand-collar-of-the-state-of-palestine/article22714293.ece|title=Modi conferred ‘Grand Collar of the State of Palestine’|last=PTI|date=2018-02-10|work=The Hindu|access-date=2025-10-23|language=en-IN}}</ref> * ಪ್ರಧಾನಿ ನರೇಂದ್ರ ಮೋದಿ ಅಫ್ಘಾನಿಸ್ತಾನದ ಅಮೀರ್ ಅಬ್ದುಲ್ಲಾ ಖಾನ್ ಪ್ರಶಸ್ತಿನ್ ಕೊರ್ತೆರ್ - ಜೂನ್ ೪, ೨೦೧೬ <ref>https://www.narendramodi.in/pm-modi-presented-with-amir-amanullah-khan-award-afghanistan-s-highest-civilian-honour--484015</ref> * ಮೋದಿ ಸೌದಿ ಅರೇಬಿಯಾದ ರಾಜ ಅಬ್ದುಲಾಜೀಜ್ ಸ್ಯಾಶ್ ಪ್ರಶಸ್ತಿನ್ ಕೊರ್ತೆರ್ - ಏಪ್ರಿಲ್ ೩, ೨೦೧೬ <ref>{{Cite web|title=PM Modi conferred Saudi’s highest civilian honour|url=https://indianexpress.com/article/india/india-news-india/modi-saudi-arabia-king-abdulaziz-sash-civilian-honour/|website=The Indian Express|date=2016-04-03|accessdate=2025-10-23|language=en}}</ref> [[ಫೈಲ್:Prime Minister Narendra Modi with his mother.jpg|thumb|ಪ್ರಧಾನಿ ಮೋದಿ ಅರೆನ ಅಪ್ಪೆನೊಟ್ಟುಗು]] * ಉಡುಪಿಡ್ ಪರ್ಯಾಯ ಶ್ರೀ ಪುತ್ತಿಗೆ ಮಠದ ಶ್ರೀ ಸುಗುಣೇಂದ್ರ ತೀರ್ಥ ಸ್ವಾಮೀಜಿಯೆರ್ ನವೆಂಬರ್ ೨೮, ೨೦೨೫ ಶುಕ್ರವಾರದಾನಿ ನರೇಂದ್ರ ಮೋದಿಗ್ 'ಭಾರತ ಭಾಗ್ಯ ವಿಧಾತ' ಪನ್ಪಿ ಬಿರುದು ಕೊರ್ದು ಮಾನಾದಿಗೆ ಮಲ್ತೆರ್.<ref> https://www.newindianexpress.com/states/karnataka/2025/Nov/29/puthige-seer-calls-pm-modi-bharata-bhagya-vidhata-seeks-udupi-corridor</ref> == ತೂಲೆ == * ಭಾರತದ ಪ್ರಧಾನ ಮಂತ್ರಿ * ಭಾರತದ ಸಚಿವ ಪರಿಷತ್ ೨೦೧೪ == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ಪ್ರಧಾನ ಮಂತ್ರಿ]] [[ವರ್ಗೊ:ಮುಖ್ಯಮಂತ್ರಿ]] scgmjtg1wtr7o3ntj8a6us8p7k0isf0 ನಿರ್ನಾಲೊ 0 4403 360716 359060 2026-05-16T07:18:30Z ChiK 1136 added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360716 wikitext text/x-wiki '''ನಿರ್ನಾಲೊ''' ತುಳುತ ಆಜನೆ ತಿಂಗೊಲು ತಿಂಗೊಲು. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || ನಿರ್ನಾಲ || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 28c6t5ip6z8efafhxkacyvisf10prsk ಪೆರಾರ್ದೆ 0 4490 360719 359063 2026-05-16T07:19:18Z ChiK 1136 added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360719 wikitext text/x-wiki ತುಳುತ ಒರ್ಂಬನೆ ತಿಂಗೊಲು '''ಪೆರಾರ್ದೆ''' ತಿಂಗೊಲು. ಪೆರಾರ್ತೆ ತಿಂಗೊಲುಂದುಲಾ ಪನ್ಪೆರ್. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || ಪೆರಾರ್ದೆ || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == == ಉಲ್ಲೇಕೊಲು == {{Reflist}} {{ಉಲ್ಲೇಕೊ}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 7qofc0ar4t1grippiiq6rs4boz0ynj3 ಪೊನ್ನಿ 0 4500 360720 359064 2026-05-16T07:19:37Z ChiK 1136 added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360720 wikitext text/x-wiki ತುಳುತ ಪತ್ತೆನೆ ತಿಂಗೊಲು ಪೊಣ್ಣಿ ತಿಂಗೊಲು. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] ನಲಿಕೆ, ಆಟಿ ಕುಲ್ಲುನೆ,ಹಿರಿಯಕುಲೆಗ್(ಕುಲೆಕ್ಕ್ ಬಲಸುನೆ) || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋಣದ ಜೋಗಿ, ಸೋಣದ ಮದಿಮಲ್ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || ಪೊನ್ನಿ || ದಶಂಬರ-ಜನವರಿ || ಮಾದಿರ || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು,ಚೆನ್ನು,ಬಾಲೆಸಾಂತು]] [[ನಲಿಕೆ]] ಕನ್ಯಾಪು (ಮದಿಮಯೆ ಮದಿಮಲ್) || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 7f36c7t224li05j03mltdij7quf9hnp ಬೊಂತ್ಯೊಲು 0 4580 360717 359061 2026-05-16T07:18:43Z ChiK 1136 added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360717 wikitext text/x-wiki ತುಳುತ ಏಳನೆ ತಿಂಗೊಲು '''ಬೊಂತ್ಯೊಲು'''. ಇಂದೆನ್ ಪುಯಿಂತೆಲ್ಂದಲಾ ಪನ್ಪೆರ್. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || ಬೊಂತ್ಯೊಲು || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == == ಉಲ್ಲೇಕೊಲು == {{Reflist}} {{ಉಲ್ಲೇಕೊ}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] s88cv8izua9eat79atjm7qrqitozko6 ಮಾಯಿ 0 4666 360721 359065 2026-05-16T07:19:58Z ChiK 1136 removed [[Category:ತುಲು ತಿಂಗೊಲು]]; added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360721 wikitext text/x-wiki '''ಮಾಯಿ ತಿಂಗೊಲು''' ಸೌರಮಾನೊದ ಪತ್ತೊಂಜನೆ ತಿಂಗೊಲು. ಮಾಯಿ ತಿಂಗೊಲು ಕುಂಭಮಾಸೊಡು ಬರ್ಪುಂಡು. ಪಡ್ಡೋಯಿ ದೇಸೊಲೆಡ್ ಮಾಯಿ ಒಂಜಿ ತಿಂಗೊಲುದ ಹವಾಮಾನೊನು ತೆರಿಪಾವುನ ಪದೊ.<ref>{{Cite web|url=https://meteodb.com/kn/usa/maui|title=ಮಾಯಿ — ತಿಂಗಳ ಹವಾಮಾನ, ನೀರಿನ ತಾಪಮಾನ|website=meteodb.com}}</ref> == ಮಾಯಿ ಪದ ಪ್ರಯೋಗದ ಬಳಕೆ == * ಮಾಯಿ : ಮಾಮಿ ಅರ್ತೊ ಉಂಡು. * ಮಾಯಿಂದ ದೊರೆ : ಪಾಡ್ದನೊಡು ಬರ್ಪುನ ಒಂಜಿ ವ್ಯಕ್ತಿ. ಆನ್ಜೋವು ಪನ್ಪುನ ಅಂಕಿತನಾವೊ * ಮಾಯಿಲ : ಅನ್ಜೋಲೆ ಪುದರ್. * ಮಾಯಿಲು : ಪನ್ಜೋಲೆ ಪುದರ್. * ಮಾಯಿಲೆರ್ : ಮಾಯಿಲ ಪನ್ಪುನ ಒಂಜಿ ಜಾತಿ ಸೂಚಕ ಪದ. ಮೆಕ್ಲ್ ಒಂಜಿ ವರ್ಗದ ನರಮಾನ್ಯೆರ್. * ಮಾಯಿಲೊ : ಕಂಗಿಲೋ ಮಾಯಿಲೋ ಮಾಯಿದಾ ಪುಣ್ಣಮೆ.<ref>'''ತುಳು ನಿಘಂಟು : ಸಂಪುಟ ಆಜಿ'''; ೧೯೯೨. (''ತುಳು-ಕನ್ನಡ-ಇಂಗ್ಲಿಷ್ ಶಬ್ದಕೋಶ''), ಪ್ರಧಾನ ಸಂಪಾದಕೆರ್ '''ಡಾ.ಯು.ಪಿ.ಉಪಾಧ್ಯಾಯ''', ''ರಾಷ್ಟ್ರಕವಿ [[ಗೋವಿಂದ ಪೈ]] ಸಂಶೋಧನ ಕೇಂದ್ರ, ಎಂ. ಜಿ. ಎಂ. ಕಾಲೇಜು ಆವರಣ, [[ಉಡುಪಿ]], [[ಕರ್ನಾಟಕ]]''</ref> ಕಂಗಿಲು ನಲಿಕೆಡ್ ಬರ್ಪುನ ಪದೊತ ಒಂಜಿ ಸಾಲ್. * ಮಾಯಿದ ಪುಣ್ಣಮೆ : # [[ಕಂಗಿಲು]] ಪನ್ಪುನ ನಲಿಕೆಡ್ ಇಲ್ಲ್ ಇಲ್ಲ್ ಬರ್ಪುನ ಮಾರಿಬೆರ್ತುನ ಕ್ರಮೊ. # ಚೆನ್ನು ನಲಿಕೆ ಪನ್ಪಿ ಒಂಜಿ ಜನಪದ ನಲಿಕೆ ಮಾಯಿತ ಪುಣ್ಣಮೆಡ್ದ್ ಸುಗ್ಗಿದ ಪುಣ್ಣಮೆ ಮುಟ್ಟ ಇಲ್ಲ್ ಇಲ್ಲಗ್ ಬರ್ಪುನ ಕ್ರಮೊ. == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] ||*ಬೇಸಡ್ ದತ್ತ್ದ್ ಬಿತ್ತೊನುಲ ಬೇಸ್ದ ಕಜಿಪುನು ದಿಂಜವುಲ *ಬೇಸದ ಬೆಪ್ಪುಡು ಊರುಮಾತ ಉರಿಪೋಂಡು || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || ಮಾಯಿ || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]],[[ಚೆನ್ನು ನಲಿಕೆ]] || ಮಾಯಿಡ್ದ್ ಬುಕ್ಕೊ ಮರಿಯಾಲ, ಆಟಿಡ್ದ್ ಬುಕ್ಕೊ ಅರೆಗಾಲ |- | ೧೨ || [[ಸುಗ್ಗಿ]] || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == * ಮಾಯಿಡ್ದ್ ಬುಕ್ಕೊ ಮರಿಯಾಲೊ, ಆಟಿಡ್ದ್ ಬುಕ್ಕೊ ಅರೆಗಾಲ ಪನ್ಪುನ ಒಂಜಿ ಗಾದೆ ಉಂಡು. ಕುಂಭಮಾಸೊಡ್ದು ಬುಕ್ಕೊ ಮರಿಯಾಲ, ಕರ್ಕಾಟಕ ಮಾಸೊಡ್ದ್ ಬುಕ್ಕೊ ಅರೆಗಾಲ ಇಂಚ ವಾಡಿಕೆಡ್ ಉಂಡು. ಮಾಯಿಗ್ ಚಳಿ ಮರಕ್ಕ್ ಬಡ್ತುನೆಗೆ ಪನ್ಪುನ ಬಾಸೆಲಾ ಉಂಡು. ಮಾಯಿಡ್ ಬರ್ಸೊ ಬತ್ತ್‌ಂಡ ಮಲೆ ಬುಲೆವುಗೆ * ಮಾಯಿದ ನಡಾವಳಿ : ಮಾಯಿ ತಿಂಗೊಲುಡು ದೈವಲೆಗ್ ಕೊರ್ಪುನ ಧರ್ಮೊ ನೇಮೊ. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 3r4dhdyzcmjdhjvrrmc4m9t063795xa ಸುಗ್ಗಿ 0 4854 360711 359066 2026-05-16T07:14:23Z ChiK 1136 added [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360711 wikitext text/x-wiki '''ಸುಗ್ಗಿ ತಿಂಗೊಲು''' ತುಲುತ ಪದಿರಾಡನೆ ತಿಂಗೊಲು. ಸೌರಮಾನೊದ ಪದ್‍ರಾಡನೆ ತಿಂಗೊಲು. ಮೀನ ಮಾಸ.<ref>'''ತುಳು ನಿಘಂಟು : ಸಂಪುಟ ಆಜಿ'''; ೧೯೯೨. (''ತುಳು-ಕನ್ನಡ-ಇಂಗ್ಲಿಷ್ ಶಬ್ದಕೋಶ''), ಪ್ರಧಾನ ಸಂಪಾದಕೆರ್ '''ಡಾ.ಯು.ಪಿ.ಉಪಾಧ್ಯಾಯ''', ''ರಾಷ್ಟ್ರಕವಿ ಗೋವಿಂದ ಪೈ ಸಂಶೋಧನ ಕೇಂದ್ರ, ಎಂ.ಜಿ.ಎಂ. ಕಾಲೇಜು ಆವರಣ, [[ಉಡುಪಿ]], [[ಕರ್ನಾಟಕ]]''</ref> == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || ಸುಗ್ಗಿ || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == * ಮಾರುನ ಮುಂಬುನ ಸುಗ್ಗಿಪಗ್ಗುಡು ಮಾರ್ಂಡ್. * ಮಾರುನ ಪೆತ್ತೆರುಲೆನ್ ಸುಗ್ಗಿಪಗ್ಗು ತಿಂಗೊಲುಡೆ ಮಾರ್‍ದಾಂಡ್. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಲು ತಿಂಗೊಲು]] [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 9a18e3rpr88sffsa5qsxiax1ugwnbq0 360712 360711 2026-05-16T07:14:30Z ChiK 1136 removed [[Category:ತುಲು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360712 wikitext text/x-wiki '''ಸುಗ್ಗಿ ತಿಂಗೊಲು''' ತುಲುತ ಪದಿರಾಡನೆ ತಿಂಗೊಲು. ಸೌರಮಾನೊದ ಪದ್‍ರಾಡನೆ ತಿಂಗೊಲು. ಮೀನ ಮಾಸ.<ref>'''ತುಳು ನಿಘಂಟು : ಸಂಪುಟ ಆಜಿ'''; ೧೯೯೨. (''ತುಳು-ಕನ್ನಡ-ಇಂಗ್ಲಿಷ್ ಶಬ್ದಕೋಶ''), ಪ್ರಧಾನ ಸಂಪಾದಕೆರ್ '''ಡಾ.ಯು.ಪಿ.ಉಪಾಧ್ಯಾಯ''', ''ರಾಷ್ಟ್ರಕವಿ ಗೋವಿಂದ ಪೈ ಸಂಶೋಧನ ಕೇಂದ್ರ, ಎಂ.ಜಿ.ಎಂ. ಕಾಲೇಜು ಆವರಣ, [[ಉಡುಪಿ]], [[ಕರ್ನಾಟಕ]]''</ref> == ತುಳುವೆರೆ ಪದ್ರಾಡ್ ತಿಂಗೊಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ ಪಗ್ಗುಡ್ದ್ ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ ಮುಟ್ಟ. ತುಳುತ 12 ತಿಂಗೊಲುದ ಪುದರ್ ಬುಕ್ಕೊ ಬೇತೆ ಬಾಸೆಲೆ ಪಂಚಾಂಗೊದ ವರ್ಸೊದ ಪಂಚಾಂಗೊಲು<ref name="Elements of South-Indian Palæography">{{cite book |author=Arthur Coke Burnell |url=https://books.google.com/books?id=lnVAAAAAMAAJ |title=Elements of South-Indian Palæography, from the Fourth to the Seventeenth Century, A. D.: Being an Introduction to the Study of South-Indian Inscriptions and Mss |publisher=Trübner & Company, 1878 |year=1878 |pages=76/147}}</ref> {| class="wikitable" style="margin: 1em auto 1em auto" ! style="background:Sky Blue" |ಕ್ರಮ ಸಂಕ್ಯೆ. ! style="background:Sky Blue" |[[ತುಳು ತಿಂಗೊಲು| ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |[[:en:Malayalam calendar|ಮಲಯಾಳಿ ಪಂಚಾಂಗೊ]] ! style="background:Sky Blue" |ಶಾಲಿವಾಹನ ಶಕ ! style="background:Sky Blue" |[[:en:Saka era|ರಾಷ್ಟ್ರೀಯ ಶಕ]] ! style="background:Sky Blue" |[[:en:Tamil calendar|ತಮಿಳು ಪಂಚಾಂಗ]] ! style="background:Sky Blue" |[[:en:Astrological sign#Western zodiac signs|ರಾಶಿಚಕ್ರದ ಚಿಹ್ನೆ]] ! style="background:Sky Blue" |[[:en:Gregorian Calendar|ಗ್ರೆಗೋರಿಯನ್ ಕ್ಯಾಲೆಂಡರ್r]] ! style="background:Sky Blue" |[[ಹಿಜರಿ ಕ್ಯಾಲೆಂಡರ್]] |- ! style="background:White" |1. ! style="background:White" |[[ಪಗ್ಗು]] ! style="background:White" |Mēṭam ! style="background:White" |[[:en:Meṣa|ಮೇಷ]] ! style="background:White" |Chaitra– Vaiśākha ! style="background:White" |Chithirai ! style="background:White" |Aries ! style="background:White" |[[:kn:ಏಪ್ರಿಲ್|ಎಪ್ರಿಲ್]]-ಮೇ ! style="background:White" |ಶವ್ವಾಲ್-ಜಿಲ್ಖಾಯದ್ |- ! style="background:White" |2. ! style="background:White" |[[ಬೇಸ]] ! style="background:White" |Iṭavam ! style="background:White" |[[:en:Vṛṣabha|ವೃಷಭ]] ! style="background:White" |Vaiśākha–Jyaiṣṭha ! style="background:White" |Vaikasi ! style="background:White" |Taurus ! style="background:White" |[[:kn:ಮೇ|ಮೇ]]-ಜೂನ್ ! style="background:White" |ಜಿಲ್ಖಾಯದ್-ಚಿಲ್ಹಜ್ |- ! style="background:White" |3. ! style="background:White" |[[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತಿಂಗೊಲು]] ! style="background:White" |Mithuṉam ! style="background:White" |[[:en:Mithuna (month)|ಮಿಥುನ]] ! style="background:White" |Jyaiṣṭha–Āṣāḍha ! style="background:White" | Aani ! style="background:White" |Gemini ! style="background:White" |[[:kn:ಜೂನ್|ಜೂನ್]]-ಜುಲೈ ! style="background:White" |ಜಿಲ್ಹಜ್-ಮೊಹರಂ |- ! style="background:White" |4. ! style="background:White" |[[ಆಟಿ]] ! style="background:White" |Kaṟkkaṭakam ! style="background:White" |[[:en:Karkaṭa|ಕರ್ಕಾಟಕ]] ! style="background:White" |Āṣāḍha–Śrāvaṇa ! style="background:White" | Aadi ! style="background:White" |Cancer ! style="background:White" |[[:kn:ಜುಲೈ|ಜುಲಾಯಿ]]-ಆಗಸ್ಟ್ ! style="background:White" |ಮೊಹರಂ-ಸಫರ್ |- ! style="background:White" |5. ! style="background:White" |[[ಸೋಣೊ]] ! style="background:White" |Chingam ! style="background:White" |[[:en:Siṃha|ಸಿಂಹ]] ! style="background:White" |Śravana–Bhādrapada ! style="background:White" |Aavani ! style="background:White" |Leo ! style="background:White" |[[:kn:ಆಗಸ್ಟ್|ಅಗೋಸ್ಟು]]-ಸೆಪ್ಟೆಂಬರ ! style="background:White" |ಸಫರ್-ರಬಿಲಾವಲ್ |- ! style="background:White" |6. ! style="background:White" |[[ನಿರ್ನಾಲೊ]]/ಕನ್ಯಾ ! style="background:White" |Kaṉṉi ! style="background:White" |[[:en:Kanyā|ಕನ್ಯಾ]] ! style="background:White" |Bhādrapada–Aśvina ! style="background:White" |Purattasi ! style="background:White" |Virgo ! style="background:White" |[[:kn:ಸೆಪ್ಟೆಂಬರ್|ಸೆಪ್ಟಂಬರೊ]]-ಅಕ್ಟೋಬರ ! style="background:White" |ರಬಿಲಾವಲ್-ರಬಿಲಾಖರ್ |- ! style="background:White" |7. ! style="background:White" |[[ಬೊಂತ್ಯೊಲು]] ! style="background:White" |Thulām ! style="background:White" |[[:en:Tulā|ತುಲಾ]] ! style="background:White" |Aśvina–Kārtika ! style="background:White" |Aippasi ! style="background:White" |Libra ! style="background:White" |[[:kn:ಅಕ್ಟೋಬರ್|ಅಕ್ಟೋಬರ]]-ನವಂಬರ ! style="background:White" |ರಬಿಲಾಖರ್-ಜಮಾದಿಲಾವಲ್ |- ! style="background:White" |8. ! style="background:White" |[[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] ! style="background:White" |Vr̥śchikam ! style="background:White" |[[:en:Vṛścika|ವೃಶ್ಚಿಕ]] ! style="background:White" |Kārtika–Mārgaśīrṣa ! style="background:White" |Karthigai ! style="background:White" |Scorpio ! style="background:White" |[[:kn:ನವೆಂಬರ್|ನವಂಬರೊ]]-ದಸಂಬರೊ ! style="background:White" |ಜಮಾದಿಲಾವಲ್-ಜಮಾದಿಲಾಖರ್ |- ! style="background:White" |9. ! style="background:White" |[[ಪೆರಾರ್ದೆ]] ! style="background:White" |Dhaṉu ! style="background:White" |[[:en:Dhanu (month)|ಧನು]] ! style="background:White" |Mārgaśīrṣa–Pauṣa ! style="background:White" |Margazhi ! style="background:White" |Sagittarius ! style="background:White" |[[:kn:ಡಿಸೆಂಬರ್|ದಶಂಬರೊ]]-ಜನವರಿ ! style="background:White" |ಜಮಾದಿಲಾಖರ್-ರಜಬ್ |- ! style="background:White" |10. ! style="background:White" |[[ಪೊನ್ನಿ]]/ಪುಯಿಂತೆಲ್ ! style="background:White" |Makaram ! style="background:White" |[[:en:Makara (month)|ಮಕರ]] ! style="background:White" |Pauṣa/Taiṣya-Māgha ! style="background:White" |Thai ! style="background:White" |Capricorn ! style="background:White" |[[:kn:ಜನವರಿ|ಜನವರಿ]]-ಪೆಬ್ರವರಿ ! style="background:White" |ರಜಬ್-ಶಾಬಾನ್ |- ! style="background:White" |11. ! style="background:White" |[[ಮಾಯಿ]] ! style="background:White" |Kumbham ! style="background:White" |[[:en:Kumbha (month)|ಕುಂಭ]] ! style="background:White" |Māgha–Phālguna ! style="background:White" |Maasi ! style="background:White" |Aquarius ! style="background:White" |[[:kn:ಫೆಬ್ರವರಿ|ಪೆಬ್ರವರಿ]]-ಮಾರ್ಚ್ ! style="background:White" |ಶಾಬಾನ್-ರಮ್ಜಾನ್ |- ! style="background:White" |12. ! style="background:White" |[[ಸುಗ್ಗಿ]] ! style="background:White" |Meeṉam ! style="background:White" |[[:en:Mīna|ಮೀನ]] ! style="background:White" |Phālguna–Chaitra ! style="background:White" |Panguni ! style="background:White" |Pisces ! style="background:White" |[[:kn:ಮಾರ್ಚ್|ಮಾರ್ಚ್]]-ಎಪ್ರಿಲ್ ! style="background:White" |ರಮ್ಜಾನ್-ಶವ್ವಾಲ್ |} == ತುಳುತ್ತ ತಿಂಗೊಲುಲು == ತುಳುವೆರೆನ ಪದ್ರಾಡ್ ತಿಂಗೊಲು ಇಂಚ : ಪಗ್ಗು, ಬೇಸ, ಕಾರ್ತೆಲ್, ಆಟಿ, ಸೋಣೊ, ನಿರ್ನಾಲ, ಬೊಂತೆಲ್, ಜಾರ್ದೆ, ಪೆರಾರ್ದೆ, ಪೊನ್ನಿ, ಮಾಯಿ, ಸುಗ್ಗಿ.<ref>https://web.archive.org/web/20151229054724/https://vanihegde.wordpress.com/2013/06/20/9220/</ref> {| class="wikitable" |- ! ಸಂಕ್ಯೆ !! ತಿಂಗೊಲು !! ಕನ್ನಡ ತಿಂಗೊಲು !! ಆಚರಣೆಲು !! [[ಗಾದೆಲು]] |- | ೦೧ || [[ಪಗ್ಗು]] || ಮಾರ್ಚ್-ಏಪ್ರಿಲ್ || [[ಬಿಸು ಪರ್ಬ]], ಕೈಬಿತ್ತ್ ದೀಡುನೆ, ನೇಜಿ ಪಾಡುನೆ || |- | ೦೨ || [[ಬೇಸ]]|| ಏಪ್ರಿಲ್-ಮೇ || [[ಪತ್ತನಾಜೆ]] || |- | ೦೩ || [[ಕಾರ್ತಿಂಗೊಲು|ಕಾರ್ತೆಲ್/ಕಾರ್ತ್ಯೊಲ್]] || ಮೇ-ಜೂನ್ || ಗುರುಕಾರ್ನೆರೆಗ್ ಬಲಸುನೆ || |- | ೦೪ || [[ಆಟಿ]] || ಜೂನ್-ಜುಲೈ || [[ಆಟಿಕಳೆಂಜೆ|ಆಟಿಕಲೆಂಜೆ]] [[ನಲಿಕೆ]], ಆಟಿ ಕುಲ್ಲುನೆ || ಆಟಿದ ಬರ್ಸೊ ಆನೆದ ಬೆರಿ ಪುಡಾವು |- | ೦೫ || [[ಸೋಣೊ|ಸೋಣ]] || ಜುಲೈ-ಆಗಸ್ಟ್ || ಸೋನಂತ ಜೋಗಿ ನಲಿಕೆ || |- | ೦೬ || [[ನಿರ್ನಾಲೊ|ನಿರ್ನಾಲ]] || ಆಗಸ್ಟ್-ಸೆಪ್ಟೆಂಬರ್ || || |- | ೦೭ || [[ಬೊಂತ್ಯೊಲು]] || ಸೆಪ್ಟೆಂಬರ್-ಅಕ್ಟೋಬರ್ || || |- | ೦೮ || [[ಜಾರ್ತೆ|ಜಾರ್ದೆ]] || ಅಕ್ಟೋಬರ್-ನವಂಬರ || || |- | ೦೯ || [[ಪೆರಾರ್ದೆ]] || ನವಂಬರ-ದಶಂಬರ || || |- | ೧೦ || [[ಪೊನ್ನಿ]] || ದಶಂಬರ-ಜನವರಿ || || |- | ೧೧ || [[ಮಾಯಿ]] || ಜನವರಿ-ಫೆಬ್ರವರಿ || [[ಕರ್ಂಗೋಲು|ಕರಂಗೋಲು]] [[ನಲಿಕೆ]] || |- | ೧೨ || ಸುಗ್ಗಿ || ಫೆಬ್ರವರಿ-ಮಾರ್ಚ್ || ಸುಗ್ಗಿ ನಲಿಕೆ [[ಕಂಗೀಲು]] || |} == ನಂಬಿಕೆ == * ಮಾರುನ ಮುಂಬುನ ಸುಗ್ಗಿಪಗ್ಗುಡು ಮಾರ್ಂಡ್. * ಮಾರುನ ಪೆತ್ತೆರುಲೆನ್ ಸುಗ್ಗಿಪಗ್ಗು ತಿಂಗೊಲುಡೆ ಮಾರ್‍ದಾಂಡ್. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 4u9th0wgi8olxp3srmizevbv4we4jvb ಟೆಂಪ್ಲೇಟ್:Merge from 10 5961 360807 360447 2026-05-16T09:47:24Z ChiK 1136 360807 wikitext text/x-wiki {{SAFESUBST:<noinclude />#invoke:Unsubst||date=__DATE__ |$B= {{#switch:{{NAMESPACE}} |Category=<span class="error">For categories please use the templates available at [[Wikipedia:Categories for discussion]].</span> |Template=<includeonly><span class="error">For templates, please use the templates available at [[Wikipedia:Templates for discussion]].</span>[[Category:Pages with templates in the wrong namespace]]</includeonly> }}{{Mbox | name = Merge from | demospace={{{demospace|}}} | type = move | image = [[File:Mergefrom.svg|50px|alt=|link=]] | text = {{#ifeq:{{{multiplesections}}}|yes|ಈ ಲೇಖನದ ಮಸ್ತ್ ಇಬಾಗೊಲೆನ್&nbsp;}}{{Pagelist|delim=''|{{{1|<noinclude>''ಒಂಜಿ ಲೇಖನೊ''</noinclude>}}}|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}|{{{6|}}}|{{{7|}}}|{{{8|}}}|{{{9|}}}|{{{10|}}}|{{{11|}}}|{{{12|}}}|{{{13|}}}|{{{14|}}}|{{{15|}}}|{{{16|}}}|{{{17|}}}|{{{18|}}}|{{{19|}}}|{{{20|}}}}}‍''ನು'' ಈ {{#if:{{{section|}}}|ಇಬಾಗೊಗು|{{#if:{{NAMESPACE}}|ಪುಟೊಕು|ಲೇಕನೊಗು}}}} '''[[Wikipedia:Merging|ಸೇರ್ಪಡೆ ಮಲ್ಪೊಡು]]''' ಪಂಡ್‍ದ್ ಸಲಹೆ ಉಂಡು. ('''[[{{#if:{{{afd|}}}|Wikipedia:Articles for deletion/{{{afd}}}|{{{discussion|{{{discuss|{{{talk|{{TALKPAGENAME}}}}}}}}}}}}}|ಚರ್ಚೆ ಮಲ್ಪುಲೆ]]'''){{#if:{{{date<includeonly>|</includeonly>}}}|<small>'' {{{date<includeonly>|</includeonly>}}}ಡ್ದ್ ಪ್ರಸ್ತಾಪ ಮಲ್ತೆರ್.''</small>}} }}<includeonly>{{#switch:{{NAMESPACE}} ||Talk={{DMC|{{{date|}}}|ರ್ದ್|ವಿಲೀನ ಮಲ್ಪೊಡಾಯಿನ ಲೇಕನೊಲು|ವಿಲೀನ ಮಲ್ಪೊಡಾಯಿನ ಮಾತ ಲೇಕನೊಲು}} |User|User talk= |#default={{#if:{{{demospace|}}}||{{DMC|||Miscellany proposed for merging}}}}}}{{Merge partner|{{{1|}}}}}</includeonly> }}<noinclude> {{Documentation|Template:Merge/doc}} <!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --> </noinclude> i8h7gua112egys56313kdl07brvjtyh ಮಾದ್ಯಮೊವಿಕಿ:Gadget-ProveIt.js 8 7603 360726 218092 2026-02-03T14:36:53Z en>Sophivorus 0 Fix lint error 360726 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Preferred date format, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options 'proveit-date-format': { year: 'numeric', month: 'long', day: 'numeric' }, // Revision tag defined at Special:Tags 'proveit-tag': 'ProveIt edit', // Automatic edit summary 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( () => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); 9x5twl8ctsrqs702cbjcwidvmaiiz0w 360727 359667 2026-05-16T07:31:59Z ChiK 1136 ೧ revisions imported from [[:en:MediaWiki:Gadget-ProveIt.js]] 359667 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Local citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite book', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite journal', 'Cite news', 'Cite paper', 'Cite report', 'Cite sign', 'Cite speech', 'Cite thesis', 'Cite video', 'Cite web', 'R', 'Sfn', ], // Citation templates that shouldn't go inside <ref> tags //'proveit-templates-noref': [ 'R', 'Sfn' ], // Supported namespaces, see https://www.mediawiki.org/wiki/Manual:Namespace_constants //'proveit-namespaces': [ 0, 2 ], // Preferred date format, see https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options //'proveit-date-format': { year: 'numeric', month: 'numeric', day: 'numeric' }, // Revision tag defined at Special:Tags //'proveit-tag': 'proveit', // Automatic edit summary //'proveit-summary': 'Reference edited with [[mw:ProveIt|ProveIt]]', } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( () => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); hicuu8wi8894caqpc0bawx48e8g2h4l 360728 2010-12-11T04:55:30Z en>Mattflaschen 0 Deploy commit e6fbdc211d24 of ProveIt. 360728 javascript text/javascript /* ProveIt, commit %s, Copyright 2010, Georgia Tech Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License 2 This is a minified version. Changes can be made through our Google Code Project (http://code.google.com/p/proveit-js/) */window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace== ""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do{c+=a.offsetLeft;b+=a.offsetTop}while(a=a.offsetParent);return{left:c,top:b}},highlightLengthAtIndex:function(a,c){if(a<0||c<0)this.log("highlightStringAtIndex: invalid negative arguments");var b=this.getMWEditBox(),e=b.value,d=this.getPosition(b).top;b.value=e.substring(0,a);b.focus();b.scrollTop=1E6;d=b.scrollTop;b.value+=e.substring(a); if(d>0)b.scrollTop=d+this.HALF_EDIT_BOX_HEIGHT;jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});d=this.getPosition(b).top;window.scroll(0,d);return true},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a);if(c==-1){this.log('Target string "'+a+'" not found.');return false}return this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]},getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;if(!a.selectionStart&& document.selection)c=c.replace(/\r\n/g,"\n");return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit",a,false)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:false,shouldAddSummary:true,loadMaximized:false,includeProveItEditSummary:function(){if(this.shouldAddSummary&&!this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var b= a.getEditSummary();if(b.value.indexOf("ProveIt")==-1)b.value+=" (edited with [[User:ProveIt_GT|ProveIt]])"});this.summaryFunctionAdded=true}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded=false;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return true},clearRefBox:function(){var a=this.getRefBox();if(a==null){this.log("Ref box is not loaded yet."); return false}a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b){this.log("insertRefIntoMWEditBox: txtarea is null");return false}b=jQuery(b);var e=a.getInsertionText(c);b.textSelection("encapsulateSelection",{peri:e,replace:true});b=b.textSelection("getCaretPosition",{startAndEnd:true});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a,c){var b=jQuery("div.input-row", c),e=jQuery("#editrefname").val();a.name=e!=""?e:null;a.params={};var d,f;for(e=0;e<b.length;e++){d=b[e];f=jQuery(".paramvalue",d)[0];d=jQuery(d).hasClass("addedrow")?jQuery(".paramdesc",d)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length);this.log("paramName: "+d);f=f.value.trim();this.log("paramVal: "+f);if(d!=""&&f!="")a.params[d]=f}if(a.toString()!=a.orig)a.save=false;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a,true),b=jQuery(".selected", this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var e=jQuery("td.number",b).text();jQuery("td.number",c).text(e);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name||"");var c={},b;for(b in a.params)c[b]=a.params[b];var e=a.getDefaultParams();for(b=0;b<e.length;b++)c[e[b]]||(c[e[b]]="");e=a.getRequiredParams();var d= [],f;for(f in c)d.push(f);(f=a.getSorter())?d.sort(f):d.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<d.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,a.getDescriptions(),d[b],e[d[b]],true);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a,jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide();jQuery("#view-pane").show()}; setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,e,d,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);if(d){jQuery(i).addClass("required");jQuery(".delete-field",g).remove()}else this.activateRemoveField(g);if(f){i.attr("for",this.EDIT_PARAM_PREFIX+ e);j.attr("id",this.EDIT_PARAM_PREFIX+e);a=b[e];if(!a){this.log("Undefined description for param: "+e+". Using directly as description.");a=e}jQuery(i).text(a);jQuery(i).attr("title",e);jQuery(j).val(c[e]);jQuery(g).show()}else{jQuery(g).show("highlight",{},"slow");jQuery(".inputs",a).scrollTop(1E5)}},togglestyle:true,toggleinsert:false,split:function(a,c,b){if(Object.prototype.toString.call(c)!=="[object RegExp]")return proveit.split._nativeSplit.call(a,c,b);var e=[],d=0,f=(c.ignoreCase?"i":"")+ (c.multiline?"m":"")+(c.sticky?"y":"");c=RegExp(c.source,f+"g");var g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(b===undefined||+b<0)b=Infinity;else{b=Math.floor(+b);if(!b)return[]}for(;i=c.exec(a);){f=i.index+i[0].length;if(f>d){e.push(a.slice(d,i.index));!proveit.split._compliantExecNpcg&&i.length>1&&i[0].replace(g,function(){for(var h=1;h<arguments.length-2;h++)if(arguments[h]===undefined)i[h]=undefined});i.length>1&&i.index<a.length&&Array.prototype.push.apply(e, i.slice(1));j=i[0].length;d=f;if(e.length>=b)break}c.lastIndex===i.index&&c.lastIndex++}if(d===a.length){if(j||!c.test(""))e.push("")}else e.push(a.slice(d));return e.length>b?e.slice(0,b):e},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs."); this.clearRefBox();var a=this.getMWEditValue(),c,b={},e=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var d=0;d<a.length;d++){var f=this.makeRef(a[d]);if(f)(c=f.name)||e.push(f);else c=(c=a[d].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);if(c){if(!b[c]){b[c]={};if(!b[c].strings)b[c].strings=[]}if(f&&!b[c].reference){b[c].reference=f;e.push(f)}b[c].strings.push(a[d])}}for(a=0;a<e.length;a++){e[a].name&&e[a].setCitationStrings(b[e[a].name].strings); this.addNewElement(e[a])}},REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],e=a.match(this.REF_REGEX);if(e&&e!=null)var d= e[1]||e[2]||e[3];e=b.split(/\|/g);if(c==this.CiteReference){var f=e[0].toLowerCase().indexOf("e"),g=e[0].indexOf("}");f=e[0].substring(f+1,g!=-1?g:e[0].length).trim()}}a=new c({name:d,type:f,save:true,inMWEditBox:true,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(d=0;d<b.length;d++){e=b[d].trim().replace(/(?:\s*\|)*(.*)/,"$1");f=c[d].trim();if(f!="")a.params[e]=f}}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(b){this.type=b};this.update= function(){var b=this.toString(),e=this.getCitationStrings();if(e.length>0)for(var d=0;d<e.length;d++){if(e[d]==this.orig){proveit.log("Updating "+e[d]+" to "+b);e[d]=b}}else if(this.name!=null){proveit.log("Adding "+b+" to citationStrings");e.push(b)}};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};var c={en:{name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date (YYYY-MM-DD)",accessdate:"Access date (YYYY-MM-DD)", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date (YYYY-MM-DD)","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN", pmid:"PMID",chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL", archivedate:"Date archived",episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID"}};this.getSorter= function(){var b=this;return function(e,d){var f=b.getSortIndex(e),g=b.getSortIndex(d);return f!=-1&&g!=-1?f-g:e<d?-1:e==d?0:1}};this.getDescriptions=function(){return c[proveit.LANG]};this.isValid=function(){return true};this.getLabel=function(){var b="";if(this.params.author)b=this.params.author+"; ";else if(this.params.last){b=this.params.last;if(this.params.first)b+=", "+this.params.first;b+="; "}if(this.params.title)b+=this.params.title;if(b==""){for(var e in this.params)break;if(e)b=e}return b}; this.getInsertionText=function(b){proveit.log("getInsertionText");if(b)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null");};this.updateInText=function(){var b=proveit.getMWEditBox();if(!(!b||b==null)){b.focus();var e=proveit.getMWEditValue();e=e.replace(this.orig,this.toString());b.value=e;this.orig=this.toString();this.save=true;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(b,e){var d= this.name?'<ref name="'+this.name+'">':"<ref>";d+="{{"+b+(e?" "+this.type:"");for(var f in this.params)d+=" | "+f+"="+this.params[f];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(b){this.citationStrings=b};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news", newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(g){var i=c[g];this.type=i!=null?i:g};proveit.AbstractReference.call(this,a);this.getSortIndex=function(g){return jQuery.inArray(g,["url","title","accessdate","author","last","first","subject","subjectlink","inventor","editor","author2","last2","first2","subject2","subjectlink2","author3","last3","first3","subject3","subjectlink3", "author4","last4","first4","subject4","author5","last5","first5","author6","last6","first6","author7","last7","first7","author8","last8","first8","author9","last9","first9","authorlink","coauthors","interviewer","cointerviewers","type","encyclopedia","newsgroup","journal","booktitle","program","episodelink","series","serieslink","credits","network","station","callsign","city","airdate","began","ended","season","seriesno","number","minutes","transcript","transcripturl","people","date","year","month", "article","contribution","format","medium","newspaper","conference","work","volume","edition","issue","publisher","location","pages","page","language","isbn","issn","oclc","doi","pmid","id","archiveurl","archivedate","time","quote","ref"])};this.toString=function(){return this.toStringInternal("cite",true)};var b={web:{url:true,title:true},book:{title:true},journal:{title:true},conference:{title:true},encyclopedia:{title:true,encyclopedia:true},news:{title:true},newsgroup:{title:true},"press release":{title:true}, interview:{last:true},episode:{title:true},video:{title:true}};this.getRequiredParams=function(){var g=b[this.type];return g?g:{}};var e={web:["url","title","author","accessdate","work","publisher","date","pages"],book:["title","author","authorlink","year","isbn","publisher","location","pages"],journal:["title","author","journal","volume","issue","year","month","pages","url","doi"],conference:["conference","title","booktitle","author","editor","year","month","url","id","accessdate","location","pages", "publisher"],encyclopedia:["title","encyclopedia","author","editor","accessdate","edition","year","publisher","volume","location","pages"],news:["title","author","url","publisher","date","accessdate","pages"],newsgroup:["title","author","date","newsgroup","id","url","accessdate"],"press release":["title","url","publisher","date","accessdate"],interview:["last","first","subjectlink","interviewer","title","callsign","city","date","program","accessdate"],episode:["title","series","credits","airdate", "city","network","season"],video:["people","date","url","title","medium","location","publisher"]};this.getDefaultParams=function(){var g=e[this.type];return g?g:[]};this.isValid=function(){if(this.type=="")return false;var g=this.getRequiredParams(),i=true,j;for(j in g)if(g[j]){i&=j in this.params;if(!i)break}return i};var d={web:"page_white_world.png",book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png", episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var g=d[this.type];if(g)return proveit.STATIC_BASE+g;return f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url","author","title","date","accessdate"],news:["author","title","newspaper","url","publication-place","volume","issue","date","pages"],encyclopedia:["author","editor","contribution","title","publisher","place","year","volume","pages"],book:["author","title", "publisher","place","year"],journal:["author","title","journal","volume","issue","year","pages"],patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(e){return["last","first","url","author","editor","contribution","author-link","last2","first2","author2-link","publication-date","inventor","title","issue-date","patent-number","country-code","journal","volume","newspaper","issue","date","publisher","place","year","edition","publication-place","series", "version","pages","page","id","isbn","doi","oclc","accessdate"].indexOf(e)};this.toString=function(){return this.toStringInternal("Citation",false)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]:["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+ "raw.png"}},getRefFromAddPane:function(a){var c=a.id;c=new (this.togglestyle?this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c});var b;a=jQuery(".paramlist",a)[0];for(var e=jQuery("div",a),d=0;d<e.length;d++){b=e[d];this.log("getRefFromAddPane: i: "+d+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0];a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+ b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName);this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);if(a!=""&&b!="")c.params[a]=b}c.update();this.log("Exiting getRefFromAddPane");return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,true);a.save=true;a.inMWEditBox=true},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)}, activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight",{},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0);this.clearCitePanes(c);var b=a.value,e=document.getElementById("dummyCitePane").cloneNode(true);e.id=b;jQuery(".ref-name-row",e).children("input").attr("id","addrefname");jQuery(".ref-name-row",e).children("label").attr("for", "addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({});a.type=b;b=a.getDescriptions();var d=a.getDefaultParams().slice(0);d.sort(a.getSorter());for(var f=0;f<d.length;f++)a.params[d[f]]="";this.log("changeAddPane: newRef: "+a);d=[];for(j in a.params)d.push(j);d.sort(a.getSorter());var g=a.getRequiredParams(),i=jQuery(".paramlist",e)[0];for(f=0;f<d.length;f++){var j=d[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(true);var k=jQuery(".paramdesc", h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h);k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else{h=document.getElementById("addedparamrow").cloneNode(true);jQuery(".paramdesc",h)[0].setAttribute("value",j)}h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+ a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(e).show();c.insertBefore(e,c.firstChild);this.log("Exiting changeAddPane")},createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css");var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),e=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),d=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png", alt:"ProveIt",height:30,width:118});e.append(d);b.append(e);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b);d=jQuery("<ul/>");e=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References (");var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");e.append(b);d.append(e);g=jQuery("<li/>");e=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(e);d.append(g);c.append(d); var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}});d=jQuery("<div/>",{id:"view-pane"});g=jQuery("<div/>",{"class":"scroll",style:"height: 210px;"});var j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>",{"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);d.append(g); i.append(d);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});d=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll",style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.","class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>", {"class":"paramlist"});d.append(h);d.append(g);k.append(d);var l=jQuery("<div/>",{id:"edit-buttons"});d=jQuery("<button/>",{style:"margin-right: 50px;"}).append("add field");l.append(d);d=jQuery("<span/>",{"class":"required",text:"bold"});l.append(d).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"});l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane", "class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"}));c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k);l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row", style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone());c.append(h);var o=jQuery("<div/>",{id:"add-tab",css:{display:"none"}});h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"});var m=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}),n=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});m.append(n);var p=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(p.get(0))}}), q=this.CiteReference.getTypes();k=(new this.AbstractReference({})).getDescriptions();for(l=0;l<q.length;l++)p.append(jQuery("<option/>",{value:q[l],text:k[q[l]]}));m.append(p);h.append(m);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));m=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"});n=n.clone().attr("for","citationmenu");m.append(n);var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}});n=["web","book","journal", "encyclopedia","news","patent"];for(q=0;q<n.length;q++)r.append(jQuery("<option/>",{value:n[l],text:k[n[l]]}));m.append(r);h.append(m).append(jQuery("<div/>",{"class":"addpanes",id:"citationpanes",style:"display: none;"}));o.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(d.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone());o.append(h);c.append(o);a.append(c);jQuery(document.body).prepend(a); var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(v,u){switch(u.index){case 1:s();proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(e).click(function(){jQuery(o).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check", secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0)));jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:false});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:false});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var e=this,d="",f="";if(a.params.title!=null){d=a.params.title;f=this.truncateTitle(d)}jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",d);d="";if(a.params.year)d=a.params.year;else if(a.params.date)if(f=a.params.date.match(/^([12]\d{3})/))d=f[1];var g="";if(a.params.author)g= a.params.author;else if(a.params.last)g=a.params.last;if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="";f=a.type;switch(f){case "web":j=a.params.url;break;case "book":if(a.params.isbn!=null)j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn;break;case "journal":case "conference":if(a.params.doi!=null)j="http://dx.doi.org/"+a.params.doi;break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";if(g!="")i='By: <span class="author">'+g+"</span>";if(d!="")h='Date: <span class="date">'+d+"</span>";if(f!=null){if(j!="")f='<a href="'+j+'" target="_blank">'+f+"</a>";k='Type: <span class="type">'+f+"</span>"}g="";if(f=="raw")g=k+" | "+a.toString();else if(i!="")g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i;else if(h!="")g=k!=""?h+" | "+k:h;else if(k!="")g=k;g="<p>"+g+"</p>";d=jQuery("<div />", {"class":"expanded"});jQuery(d).append(g);jQuery("td.title",b).append(d);if(!c){f=jQuery("#refs tr").length;jQuery("td.number",b).text(f);jQuery("#numRefs").text(f)}jQuery(b).click(function(){e.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});f=function(){e.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()};var l=a.getCitationStrings();g=jQuery('<span class="all-citations" />');for(j=0;j<l.length;j++){i=j+1;for(h="";i> 0;){k=--i%26;h=String.fromCharCode(97+k)+h;i=Math.floor(i/26)}i=jQuery('<a href="#">'+h+"</a>");h=function(o){return function(){var m=0,n=0,p=proveit.getMWEditValue();for(n=0;n<o;n++){m=p.indexOf(l[n],m);if(m==-1){proveit.log("citationStrings["+n+"]: "+l[n]+" not found. Returning.");return false}m+=l[n].length}m=p.indexOf(l[o],m);m==-1?proveit.log("citationStrings["+o+"]: "+l[o]+" not found."):proveit.highlightLengthAtIndex(m,l[o].length);return false}}(j);i.click(h);g.append(i)}if(l.length>1){j= jQuery("<p />");j.append('This reference is cited in the article <span class="num-citations">'+l.length+" times</span>: ").append(g);d.append(j)}if(a.type!="raw"){g=jQuery("<button />",{text:"edit"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:false});g.click(f);jQuery(".edit",b).append(g);g=jQuery("<button />",{"class":"edit",text:"edit this reference"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:true});g.click(f);d.append(g);jQuery(b).dblclick(f)}else jQuery(".edit",b).append("&nbsp;"); if(l.length>0){f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"});jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:true});f.click(function(){e.insertRefIntoMWEditBox(a,false);return false});d.append(f)}return b},truncateTitle:function(a){var c=a;if(a.length>86){c=c.substring(0,86);a=c.lastIndexOf(" ");if(a!=-1){c=c.substr(0,a);c+=" ..."}}return c},formatDate:function(a){return a.getFullYear()+"-"+(a.getMonth()<9?"0":"")+(a.getMonth()+1)+"-"+(a.getDate()< 10?"0":"")+a.getDate()},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a,false))}},window.proveit);proveit.CiteReference.getTypes=function(){return["web","book","journal","conference","encyclopedia","news","newsgroup","press release","interview","episode","video"]};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===undefined;proveit.split._nativeSplit=String.prototype.split; proveit.load(); ea58wp9fcajlfu31zw3pp9rmplzkyjb 360729 360728 2010-12-11T05:12:11Z en>Mattflaschen 0 Deploy commit e6fbdc211d24 of ProveIt. 360729 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2010, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit e6fbdc211d24 as of 2010-12-11 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace== ""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do{c+=a.offsetLeft;b+=a.offsetTop}while(a=a.offsetParent);return{left:c,top:b}},highlightLengthAtIndex:function(a,c){if(a<0||c<0)this.log("highlightStringAtIndex: invalid negative arguments");var b=this.getMWEditBox(),e=b.value,d=this.getPosition(b).top;b.value=e.substring(0,a);b.focus();b.scrollTop=1E6;d=b.scrollTop;b.value+=e.substring(a); if(d>0)b.scrollTop=d+this.HALF_EDIT_BOX_HEIGHT;jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});d=this.getPosition(b).top;window.scroll(0,d);return true},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a);if(c==-1){this.log('Target string "'+a+'" not found.');return false}return this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]},getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;if(!a.selectionStart&& document.selection)c=c.replace(/\r\n/g,"\n");return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit",a,false)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:false,shouldAddSummary:true,loadMaximized:false,includeProveItEditSummary:function(){if(this.shouldAddSummary&&!this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var b= a.getEditSummary();if(b.value.indexOf("ProveIt")==-1)b.value+=" (edited with [[User:ProveIt_GT|ProveIt]])"});this.summaryFunctionAdded=true}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded=false;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return true},clearRefBox:function(){var a=this.getRefBox();if(a==null){this.log("Ref box is not loaded yet."); return false}a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b){this.log("insertRefIntoMWEditBox: txtarea is null");return false}b=jQuery(b);var e=a.getInsertionText(c);b.textSelection("encapsulateSelection",{peri:e,replace:true});b=b.textSelection("getCaretPosition",{startAndEnd:true});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a,c){var b=jQuery("div.input-row", c),e=jQuery("#editrefname").val();a.name=e!=""?e:null;a.params={};var d,f;for(e=0;e<b.length;e++){d=b[e];f=jQuery(".paramvalue",d)[0];d=jQuery(d).hasClass("addedrow")?jQuery(".paramdesc",d)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length);this.log("paramName: "+d);f=f.value.trim();this.log("paramVal: "+f);if(d!=""&&f!="")a.params[d]=f}if(a.toString()!=a.orig)a.save=false;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a,true),b=jQuery(".selected", this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var e=jQuery("td.number",b).text();jQuery("td.number",c).text(e);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name||"");var c={},b;for(b in a.params)c[b]=a.params[b];var e=a.getDefaultParams();for(b=0;b<e.length;b++)c[e[b]]||(c[e[b]]="");e=a.getRequiredParams();var d= [],f;for(f in c)d.push(f);(f=a.getSorter())?d.sort(f):d.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<d.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,a.getDescriptions(),d[b],e[d[b]],true);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a,jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide();jQuery("#view-pane").show()}; setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,e,d,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);if(d){jQuery(i).addClass("required");jQuery(".delete-field",g).remove()}else this.activateRemoveField(g);if(f){i.attr("for",this.EDIT_PARAM_PREFIX+ e);j.attr("id",this.EDIT_PARAM_PREFIX+e);a=b[e];if(!a){this.log("Undefined description for param: "+e+". Using directly as description.");a=e}jQuery(i).text(a);jQuery(i).attr("title",e);jQuery(j).val(c[e]);jQuery(g).show()}else{jQuery(g).show("highlight",{},"slow");jQuery(".inputs",a).scrollTop(1E5)}},togglestyle:true,toggleinsert:false,split:function(a,c,b){if(Object.prototype.toString.call(c)!=="[object RegExp]")return proveit.split._nativeSplit.call(a,c,b);var e=[],d=0,f=(c.ignoreCase?"i":"")+ (c.multiline?"m":"")+(c.sticky?"y":"");c=RegExp(c.source,f+"g");var g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(b===undefined||+b<0)b=Infinity;else{b=Math.floor(+b);if(!b)return[]}for(;i=c.exec(a);){f=i.index+i[0].length;if(f>d){e.push(a.slice(d,i.index));!proveit.split._compliantExecNpcg&&i.length>1&&i[0].replace(g,function(){for(var h=1;h<arguments.length-2;h++)if(arguments[h]===undefined)i[h]=undefined});i.length>1&&i.index<a.length&&Array.prototype.push.apply(e, i.slice(1));j=i[0].length;d=f;if(e.length>=b)break}c.lastIndex===i.index&&c.lastIndex++}if(d===a.length){if(j||!c.test(""))e.push("")}else e.push(a.slice(d));return e.length>b?e.slice(0,b):e},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs."); this.clearRefBox();var a=this.getMWEditValue(),c,b={},e=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var d=0;d<a.length;d++){var f=this.makeRef(a[d]);if(f)(c=f.name)||e.push(f);else c=(c=a[d].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);if(c){if(!b[c]){b[c]={};if(!b[c].strings)b[c].strings=[]}if(f&&!b[c].reference){b[c].reference=f;e.push(f)}b[c].strings.push(a[d])}}for(a=0;a<e.length;a++){e[a].name&&e[a].setCitationStrings(b[e[a].name].strings); this.addNewElement(e[a])}},REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],e=a.match(this.REF_REGEX);if(e&&e!=null)var d= e[1]||e[2]||e[3];e=b.split(/\|/g);if(c==this.CiteReference){var f=e[0].toLowerCase().indexOf("e"),g=e[0].indexOf("}");f=e[0].substring(f+1,g!=-1?g:e[0].length).trim()}}a=new c({name:d,type:f,save:true,inMWEditBox:true,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(d=0;d<b.length;d++){e=b[d].trim().replace(/(?:\s*\|)*(.*)/,"$1");f=c[d].trim();if(f!="")a.params[e]=f}}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(b){this.type=b};this.update= function(){var b=this.toString(),e=this.getCitationStrings();if(e.length>0)for(var d=0;d<e.length;d++){if(e[d]==this.orig){proveit.log("Updating "+e[d]+" to "+b);e[d]=b}}else if(this.name!=null){proveit.log("Adding "+b+" to citationStrings");e.push(b)}};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};var c={en:{name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date (YYYY-MM-DD)",accessdate:"Access date (YYYY-MM-DD)", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date (YYYY-MM-DD)","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN", pmid:"PMID",chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL", archivedate:"Date archived",episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID"}};this.getSorter= function(){var b=this;return function(e,d){var f=b.getSortIndex(e),g=b.getSortIndex(d);return f!=-1&&g!=-1?f-g:e<d?-1:e==d?0:1}};this.getDescriptions=function(){return c[proveit.LANG]};this.isValid=function(){return true};this.getLabel=function(){var b="";if(this.params.author)b=this.params.author+"; ";else if(this.params.last){b=this.params.last;if(this.params.first)b+=", "+this.params.first;b+="; "}if(this.params.title)b+=this.params.title;if(b==""){for(var e in this.params)break;if(e)b=e}return b}; this.getInsertionText=function(b){proveit.log("getInsertionText");if(b)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null");};this.updateInText=function(){var b=proveit.getMWEditBox();if(!(!b||b==null)){b.focus();var e=proveit.getMWEditValue();e=e.replace(this.orig,this.toString());b.value=e;this.orig=this.toString();this.save=true;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(b,e){var d= this.name?'<ref name="'+this.name+'">':"<ref>";d+="{{"+b+(e?" "+this.type:"");for(var f in this.params)d+=" | "+f+"="+this.params[f];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(b){this.citationStrings=b};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news", newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(g){var i=c[g];this.type=i!=null?i:g};proveit.AbstractReference.call(this,a);this.getSortIndex=function(g){return jQuery.inArray(g,["url","title","accessdate","author","last","first","subject","subjectlink","inventor","editor","author2","last2","first2","subject2","subjectlink2","author3","last3","first3","subject3","subjectlink3", "author4","last4","first4","subject4","author5","last5","first5","author6","last6","first6","author7","last7","first7","author8","last8","first8","author9","last9","first9","authorlink","coauthors","interviewer","cointerviewers","type","encyclopedia","newsgroup","journal","booktitle","program","episodelink","series","serieslink","credits","network","station","callsign","city","airdate","began","ended","season","seriesno","number","minutes","transcript","transcripturl","people","date","year","month", "article","contribution","format","medium","newspaper","conference","work","volume","edition","issue","publisher","location","pages","page","language","isbn","issn","oclc","doi","pmid","id","archiveurl","archivedate","time","quote","ref"])};this.toString=function(){return this.toStringInternal("cite",true)};var b={web:{url:true,title:true},book:{title:true},journal:{title:true},conference:{title:true},encyclopedia:{title:true,encyclopedia:true},news:{title:true},newsgroup:{title:true},"press release":{title:true}, interview:{last:true},episode:{title:true},video:{title:true}};this.getRequiredParams=function(){var g=b[this.type];return g?g:{}};var e={web:["url","title","author","accessdate","work","publisher","date","pages"],book:["title","author","authorlink","year","isbn","publisher","location","pages"],journal:["title","author","journal","volume","issue","year","month","pages","url","doi"],conference:["conference","title","booktitle","author","editor","year","month","url","id","accessdate","location","pages", "publisher"],encyclopedia:["title","encyclopedia","author","editor","accessdate","edition","year","publisher","volume","location","pages"],news:["title","author","url","publisher","date","accessdate","pages"],newsgroup:["title","author","date","newsgroup","id","url","accessdate"],"press release":["title","url","publisher","date","accessdate"],interview:["last","first","subjectlink","interviewer","title","callsign","city","date","program","accessdate"],episode:["title","series","credits","airdate", "city","network","season"],video:["people","date","url","title","medium","location","publisher"]};this.getDefaultParams=function(){var g=e[this.type];return g?g:[]};this.isValid=function(){if(this.type=="")return false;var g=this.getRequiredParams(),i=true,j;for(j in g)if(g[j]){i&=j in this.params;if(!i)break}return i};var d={web:"page_white_world.png",book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png", episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var g=d[this.type];if(g)return proveit.STATIC_BASE+g;return f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url","author","title","date","accessdate"],news:["author","title","newspaper","url","publication-place","volume","issue","date","pages"],encyclopedia:["author","editor","contribution","title","publisher","place","year","volume","pages"],book:["author","title", "publisher","place","year"],journal:["author","title","journal","volume","issue","year","pages"],patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(e){return["last","first","url","author","editor","contribution","author-link","last2","first2","author2-link","publication-date","inventor","title","issue-date","patent-number","country-code","journal","volume","newspaper","issue","date","publisher","place","year","edition","publication-place","series", "version","pages","page","id","isbn","doi","oclc","accessdate"].indexOf(e)};this.toString=function(){return this.toStringInternal("Citation",false)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]:["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+ "raw.png"}},getRefFromAddPane:function(a){var c=a.id;c=new (this.togglestyle?this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c});var b;a=jQuery(".paramlist",a)[0];for(var e=jQuery("div",a),d=0;d<e.length;d++){b=e[d];this.log("getRefFromAddPane: i: "+d+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0];a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+ b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName);this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);if(a!=""&&b!="")c.params[a]=b}c.update();this.log("Exiting getRefFromAddPane");return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,true);a.save=true;a.inMWEditBox=true},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)}, activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight",{},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0);this.clearCitePanes(c);var b=a.value,e=document.getElementById("dummyCitePane").cloneNode(true);e.id=b;jQuery(".ref-name-row",e).children("input").attr("id","addrefname");jQuery(".ref-name-row",e).children("label").attr("for", "addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({});a.type=b;b=a.getDescriptions();var d=a.getDefaultParams().slice(0);d.sort(a.getSorter());for(var f=0;f<d.length;f++)a.params[d[f]]="";this.log("changeAddPane: newRef: "+a);d=[];for(j in a.params)d.push(j);d.sort(a.getSorter());var g=a.getRequiredParams(),i=jQuery(".paramlist",e)[0];for(f=0;f<d.length;f++){var j=d[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(true);var k=jQuery(".paramdesc", h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h);k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else{h=document.getElementById("addedparamrow").cloneNode(true);jQuery(".paramdesc",h)[0].setAttribute("value",j)}h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+ a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(e).show();c.insertBefore(e,c.firstChild);this.log("Exiting changeAddPane")},createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css");var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),e=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),d=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png", alt:"ProveIt",height:30,width:118});e.append(d);b.append(e);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b);d=jQuery("<ul/>");e=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References (");var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");e.append(b);d.append(e);g=jQuery("<li/>");e=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(e);d.append(g);c.append(d); var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}});d=jQuery("<div/>",{id:"view-pane"});g=jQuery("<div/>",{"class":"scroll",style:"height: 210px;"});var j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>",{"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);d.append(g); i.append(d);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});d=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll",style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.","class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>", {"class":"paramlist"});d.append(h);d.append(g);k.append(d);var l=jQuery("<div/>",{id:"edit-buttons"});d=jQuery("<button/>",{style:"margin-right: 50px;"}).append("add field");l.append(d);d=jQuery("<span/>",{"class":"required",text:"bold"});l.append(d).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"});l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane", "class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"}));c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k);l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row", style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone());c.append(h);var o=jQuery("<div/>",{id:"add-tab",css:{display:"none"}});h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"});var m=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}),n=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});m.append(n);var p=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(p.get(0))}}), q=this.CiteReference.getTypes();k=(new this.AbstractReference({})).getDescriptions();for(l=0;l<q.length;l++)p.append(jQuery("<option/>",{value:q[l],text:k[q[l]]}));m.append(p);h.append(m);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));m=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"});n=n.clone().attr("for","citationmenu");m.append(n);var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}});n=["web","book","journal", "encyclopedia","news","patent"];for(q=0;q<n.length;q++)r.append(jQuery("<option/>",{value:n[l],text:k[n[l]]}));m.append(r);h.append(m).append(jQuery("<div/>",{"class":"addpanes",id:"citationpanes",style:"display: none;"}));o.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(d.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone());o.append(h);c.append(o);a.append(c);jQuery(document.body).prepend(a); var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(v,u){switch(u.index){case 1:s();proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(e).click(function(){jQuery(o).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check", secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0)));jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:false});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:false});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var e=this,d="",f="";if(a.params.title!=null){d=a.params.title;f=this.truncateTitle(d)}jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",d);d="";if(a.params.year)d=a.params.year;else if(a.params.date)if(f=a.params.date.match(/^([12]\d{3})/))d=f[1];var g="";if(a.params.author)g= a.params.author;else if(a.params.last)g=a.params.last;if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="";f=a.type;switch(f){case "web":j=a.params.url;break;case "book":if(a.params.isbn!=null)j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn;break;case "journal":case "conference":if(a.params.doi!=null)j="http://dx.doi.org/"+a.params.doi;break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";if(g!="")i='By: <span class="author">'+g+"</span>";if(d!="")h='Date: <span class="date">'+d+"</span>";if(f!=null){if(j!="")f='<a href="'+j+'" target="_blank">'+f+"</a>";k='Type: <span class="type">'+f+"</span>"}g="";if(f=="raw")g=k+" | "+a.toString();else if(i!="")g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i;else if(h!="")g=k!=""?h+" | "+k:h;else if(k!="")g=k;g="<p>"+g+"</p>";d=jQuery("<div />", {"class":"expanded"});jQuery(d).append(g);jQuery("td.title",b).append(d);if(!c){f=jQuery("#refs tr").length;jQuery("td.number",b).text(f);jQuery("#numRefs").text(f)}jQuery(b).click(function(){e.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});f=function(){e.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()};var l=a.getCitationStrings();g=jQuery('<span class="all-citations" />');for(j=0;j<l.length;j++){i=j+1;for(h="";i> 0;){k=--i%26;h=String.fromCharCode(97+k)+h;i=Math.floor(i/26)}i=jQuery('<a href="#">'+h+"</a>");h=function(o){return function(){var m=0,n=0,p=proveit.getMWEditValue();for(n=0;n<o;n++){m=p.indexOf(l[n],m);if(m==-1){proveit.log("citationStrings["+n+"]: "+l[n]+" not found. Returning.");return false}m+=l[n].length}m=p.indexOf(l[o],m);m==-1?proveit.log("citationStrings["+o+"]: "+l[o]+" not found."):proveit.highlightLengthAtIndex(m,l[o].length);return false}}(j);i.click(h);g.append(i)}if(l.length>1){j= jQuery("<p />");j.append('This reference is cited in the article <span class="num-citations">'+l.length+" times</span>: ").append(g);d.append(j)}if(a.type!="raw"){g=jQuery("<button />",{text:"edit"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:false});g.click(f);jQuery(".edit",b).append(g);g=jQuery("<button />",{"class":"edit",text:"edit this reference"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:true});g.click(f);d.append(g);jQuery(b).dblclick(f)}else jQuery(".edit",b).append("&nbsp;"); if(l.length>0){f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"});jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:true});f.click(function(){e.insertRefIntoMWEditBox(a,false);return false});d.append(f)}return b},truncateTitle:function(a){var c=a;if(a.length>86){c=c.substring(0,86);a=c.lastIndexOf(" ");if(a!=-1){c=c.substr(0,a);c+=" ..."}}return c},formatDate:function(a){return a.getFullYear()+"-"+(a.getMonth()<9?"0":"")+(a.getMonth()+1)+"-"+(a.getDate()< 10?"0":"")+a.getDate()},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a,false))}},window.proveit);proveit.CiteReference.getTypes=function(){return["web","book","journal","conference","encyclopedia","news","newsgroup","press release","interview","episode","video"]};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===undefined;proveit.split._nativeSplit=String.prototype.split; proveit.load(); nuc18de093s4f8yxzmcgksbzvqdtjpy 360730 360729 2010-12-11T05:33:33Z en>Mattflaschen 0 Deploy commit e6fbdc211d24 of ProveIt. 360730 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2010, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit e6fbdc211d24 as of 2010-12-08 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace== ""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do{c+=a.offsetLeft;b+=a.offsetTop}while(a=a.offsetParent);return{left:c,top:b}},highlightLengthAtIndex:function(a,c){if(a<0||c<0)this.log("highlightStringAtIndex: invalid negative arguments");var b=this.getMWEditBox(),e=b.value,d=this.getPosition(b).top;b.value=e.substring(0,a);b.focus();b.scrollTop=1E6;d=b.scrollTop;b.value+=e.substring(a); if(d>0)b.scrollTop=d+this.HALF_EDIT_BOX_HEIGHT;jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});d=this.getPosition(b).top;window.scroll(0,d);return true},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a);if(c==-1){this.log('Target string "'+a+'" not found.');return false}return this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]},getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;if(!a.selectionStart&& document.selection)c=c.replace(/\r\n/g,"\n");return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit",a,false)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:false,shouldAddSummary:true,loadMaximized:false,includeProveItEditSummary:function(){if(this.shouldAddSummary&&!this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var b= a.getEditSummary();if(b.value.indexOf("ProveIt")==-1)b.value+=" (edited with [[User:ProveIt_GT|ProveIt]])"});this.summaryFunctionAdded=true}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded=false;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return true},clearRefBox:function(){var a=this.getRefBox();if(a==null){this.log("Ref box is not loaded yet."); return false}a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b){this.log("insertRefIntoMWEditBox: txtarea is null");return false}b=jQuery(b);var e=a.getInsertionText(c);b.textSelection("encapsulateSelection",{peri:e,replace:true});b=b.textSelection("getCaretPosition",{startAndEnd:true});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a,c){var b=jQuery("div.input-row", c),e=jQuery("#editrefname").val();a.name=e!=""?e:null;a.params={};var d,f;for(e=0;e<b.length;e++){d=b[e];f=jQuery(".paramvalue",d)[0];d=jQuery(d).hasClass("addedrow")?jQuery(".paramdesc",d)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length);this.log("paramName: "+d);f=f.value.trim();this.log("paramVal: "+f);if(d!=""&&f!="")a.params[d]=f}if(a.toString()!=a.orig)a.save=false;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a,true),b=jQuery(".selected", this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var e=jQuery("td.number",b).text();jQuery("td.number",c).text(e);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name||"");var c={},b;for(b in a.params)c[b]=a.params[b];var e=a.getDefaultParams();for(b=0;b<e.length;b++)c[e[b]]||(c[e[b]]="");e=a.getRequiredParams();var d= [],f;for(f in c)d.push(f);(f=a.getSorter())?d.sort(f):d.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<d.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,a.getDescriptions(),d[b],e[d[b]],true);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a,jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide();jQuery("#view-pane").show()}; setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,e,d,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);if(d){jQuery(i).addClass("required");jQuery(".delete-field",g).remove()}else this.activateRemoveField(g);if(f){i.attr("for",this.EDIT_PARAM_PREFIX+ e);j.attr("id",this.EDIT_PARAM_PREFIX+e);a=b[e];if(!a){this.log("Undefined description for param: "+e+". Using directly as description.");a=e}jQuery(i).text(a);jQuery(i).attr("title",e);jQuery(j).val(c[e]);jQuery(g).show()}else{jQuery(g).show("highlight",{},"slow");jQuery(".inputs",a).scrollTop(1E5)}},togglestyle:true,toggleinsert:false,split:function(a,c,b){if(Object.prototype.toString.call(c)!=="[object RegExp]")return proveit.split._nativeSplit.call(a,c,b);var e=[],d=0,f=(c.ignoreCase?"i":"")+ (c.multiline?"m":"")+(c.sticky?"y":"");c=RegExp(c.source,f+"g");var g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(b===undefined||+b<0)b=Infinity;else{b=Math.floor(+b);if(!b)return[]}for(;i=c.exec(a);){f=i.index+i[0].length;if(f>d){e.push(a.slice(d,i.index));!proveit.split._compliantExecNpcg&&i.length>1&&i[0].replace(g,function(){for(var h=1;h<arguments.length-2;h++)if(arguments[h]===undefined)i[h]=undefined});i.length>1&&i.index<a.length&&Array.prototype.push.apply(e, i.slice(1));j=i[0].length;d=f;if(e.length>=b)break}c.lastIndex===i.index&&c.lastIndex++}if(d===a.length){if(j||!c.test(""))e.push("")}else e.push(a.slice(d));return e.length>b?e.slice(0,b):e},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs."); this.clearRefBox();var a=this.getMWEditValue(),c,b={},e=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var d=0;d<a.length;d++){var f=this.makeRef(a[d]);if(f)(c=f.name)||e.push(f);else c=(c=a[d].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);if(c){if(!b[c]){b[c]={};if(!b[c].strings)b[c].strings=[]}if(f&&!b[c].reference){b[c].reference=f;e.push(f)}b[c].strings.push(a[d])}}for(a=0;a<e.length;a++){e[a].name&&e[a].setCitationStrings(b[e[a].name].strings); this.addNewElement(e[a])}},REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],e=a.match(this.REF_REGEX);if(e&&e!=null)var d= e[1]||e[2]||e[3];e=b.split(/\|/g);if(c==this.CiteReference){var f=e[0].toLowerCase().indexOf("e"),g=e[0].indexOf("}");f=e[0].substring(f+1,g!=-1?g:e[0].length).trim()}}a=new c({name:d,type:f,save:true,inMWEditBox:true,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(d=0;d<b.length;d++){e=b[d].trim().replace(/(?:\s*\|)*(.*)/,"$1");f=c[d].trim();if(f!="")a.params[e]=f}}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(b){this.type=b};this.update= function(){var b=this.toString(),e=this.getCitationStrings();if(e.length>0)for(var d=0;d<e.length;d++){if(e[d]==this.orig){proveit.log("Updating "+e[d]+" to "+b);e[d]=b}}else if(this.name!=null){proveit.log("Adding "+b+" to citationStrings");e.push(b)}};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};var c={en:{name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date (YYYY-MM-DD)",accessdate:"Access date (YYYY-MM-DD)", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date (YYYY-MM-DD)","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN", pmid:"PMID",chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL", archivedate:"Date archived",episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID"}};this.getSorter= function(){var b=this;return function(e,d){var f=b.getSortIndex(e),g=b.getSortIndex(d);return f!=-1&&g!=-1?f-g:e<d?-1:e==d?0:1}};this.getDescriptions=function(){return c[proveit.LANG]};this.isValid=function(){return true};this.getLabel=function(){var b="";if(this.params.author)b=this.params.author+"; ";else if(this.params.last){b=this.params.last;if(this.params.first)b+=", "+this.params.first;b+="; "}if(this.params.title)b+=this.params.title;if(b==""){for(var e in this.params)break;if(e)b=e}return b}; this.getInsertionText=function(b){proveit.log("getInsertionText");if(b)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null");};this.updateInText=function(){var b=proveit.getMWEditBox();if(!(!b||b==null)){b.focus();var e=proveit.getMWEditValue();e=e.replace(this.orig,this.toString());b.value=e;this.orig=this.toString();this.save=true;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(b,e){var d= this.name?'<ref name="'+this.name+'">':"<ref>";d+="{{"+b+(e?" "+this.type:"");for(var f in this.params)d+=" | "+f+"="+this.params[f];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(b){this.citationStrings=b};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news", newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(g){var i=c[g];this.type=i!=null?i:g};proveit.AbstractReference.call(this,a);this.getSortIndex=function(g){return jQuery.inArray(g,["url","title","accessdate","author","last","first","subject","subjectlink","inventor","editor","author2","last2","first2","subject2","subjectlink2","author3","last3","first3","subject3","subjectlink3", "author4","last4","first4","subject4","author5","last5","first5","author6","last6","first6","author7","last7","first7","author8","last8","first8","author9","last9","first9","authorlink","coauthors","interviewer","cointerviewers","type","encyclopedia","newsgroup","journal","booktitle","program","episodelink","series","serieslink","credits","network","station","callsign","city","airdate","began","ended","season","seriesno","number","minutes","transcript","transcripturl","people","date","year","month", "article","contribution","format","medium","newspaper","conference","work","volume","edition","issue","publisher","location","pages","page","language","isbn","issn","oclc","doi","pmid","id","archiveurl","archivedate","time","quote","ref"])};this.toString=function(){return this.toStringInternal("cite",true)};var b={web:{url:true,title:true},book:{title:true},journal:{title:true},conference:{title:true},encyclopedia:{title:true,encyclopedia:true},news:{title:true},newsgroup:{title:true},"press release":{title:true}, interview:{last:true},episode:{title:true},video:{title:true}};this.getRequiredParams=function(){var g=b[this.type];return g?g:{}};var e={web:["url","title","author","accessdate","work","publisher","date","pages"],book:["title","author","authorlink","year","isbn","publisher","location","pages"],journal:["title","author","journal","volume","issue","year","month","pages","url","doi"],conference:["conference","title","booktitle","author","editor","year","month","url","id","accessdate","location","pages", "publisher"],encyclopedia:["title","encyclopedia","author","editor","accessdate","edition","year","publisher","volume","location","pages"],news:["title","author","url","publisher","date","accessdate","pages"],newsgroup:["title","author","date","newsgroup","id","url","accessdate"],"press release":["title","url","publisher","date","accessdate"],interview:["last","first","subjectlink","interviewer","title","callsign","city","date","program","accessdate"],episode:["title","series","credits","airdate", "city","network","season"],video:["people","date","url","title","medium","location","publisher"]};this.getDefaultParams=function(){var g=e[this.type];return g?g:[]};this.isValid=function(){if(this.type=="")return false;var g=this.getRequiredParams(),i=true,j;for(j in g)if(g[j]){i&=j in this.params;if(!i)break}return i};var d={web:"page_white_world.png",book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png", episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var g=d[this.type];if(g)return proveit.STATIC_BASE+g;return f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url","author","title","date","accessdate"],news:["author","title","newspaper","url","publication-place","volume","issue","date","pages"],encyclopedia:["author","editor","contribution","title","publisher","place","year","volume","pages"],book:["author","title", "publisher","place","year"],journal:["author","title","journal","volume","issue","year","pages"],patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(e){return["last","first","url","author","editor","contribution","author-link","last2","first2","author2-link","publication-date","inventor","title","issue-date","patent-number","country-code","journal","volume","newspaper","issue","date","publisher","place","year","edition","publication-place","series", "version","pages","page","id","isbn","doi","oclc","accessdate"].indexOf(e)};this.toString=function(){return this.toStringInternal("Citation",false)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]:["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+ "raw.png"}},getRefFromAddPane:function(a){var c=a.id;c=new (this.togglestyle?this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c});var b;a=jQuery(".paramlist",a)[0];for(var e=jQuery("div",a),d=0;d<e.length;d++){b=e[d];this.log("getRefFromAddPane: i: "+d+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0];a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+ b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName);this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);if(a!=""&&b!="")c.params[a]=b}c.update();this.log("Exiting getRefFromAddPane");return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,true);a.save=true;a.inMWEditBox=true},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)}, activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight",{},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0);this.clearCitePanes(c);var b=a.value,e=document.getElementById("dummyCitePane").cloneNode(true);e.id=b;jQuery(".ref-name-row",e).children("input").attr("id","addrefname");jQuery(".ref-name-row",e).children("label").attr("for", "addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({});a.type=b;b=a.getDescriptions();var d=a.getDefaultParams().slice(0);d.sort(a.getSorter());for(var f=0;f<d.length;f++)a.params[d[f]]="";this.log("changeAddPane: newRef: "+a);d=[];for(j in a.params)d.push(j);d.sort(a.getSorter());var g=a.getRequiredParams(),i=jQuery(".paramlist",e)[0];for(f=0;f<d.length;f++){var j=d[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(true);var k=jQuery(".paramdesc", h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h);k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else{h=document.getElementById("addedparamrow").cloneNode(true);jQuery(".paramdesc",h)[0].setAttribute("value",j)}h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+ a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(e).show();c.insertBefore(e,c.firstChild);this.log("Exiting changeAddPane")},createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css");var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),e=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),d=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png", alt:"ProveIt",height:30,width:118});e.append(d);b.append(e);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b);d=jQuery("<ul/>");e=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References (");var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");e.append(b);d.append(e);g=jQuery("<li/>");e=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(e);d.append(g);c.append(d); var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}});d=jQuery("<div/>",{id:"view-pane"});g=jQuery("<div/>",{"class":"scroll",style:"height: 210px;"});var j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>",{"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);d.append(g); i.append(d);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});d=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll",style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.","class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>", {"class":"paramlist"});d.append(h);d.append(g);k.append(d);var l=jQuery("<div/>",{id:"edit-buttons"});d=jQuery("<button/>",{style:"margin-right: 50px;"}).append("add field");l.append(d);d=jQuery("<span/>",{"class":"required",text:"bold"});l.append(d).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"});l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane", "class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"}));c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k);l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row", style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone());c.append(h);var o=jQuery("<div/>",{id:"add-tab",css:{display:"none"}});h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"});var m=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}),n=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});m.append(n);var p=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(p.get(0))}}), q=this.CiteReference.getTypes();k=(new this.AbstractReference({})).getDescriptions();for(l=0;l<q.length;l++)p.append(jQuery("<option/>",{value:q[l],text:k[q[l]]}));m.append(p);h.append(m);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));m=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"});n=n.clone().attr("for","citationmenu");m.append(n);var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}});n=["web","book","journal", "encyclopedia","news","patent"];for(q=0;q<n.length;q++)r.append(jQuery("<option/>",{value:n[l],text:k[n[l]]}));m.append(r);h.append(m).append(jQuery("<div/>",{"class":"addpanes",id:"citationpanes",style:"display: none;"}));o.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(d.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone());o.append(h);c.append(o);a.append(c);jQuery(document.body).prepend(a); var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(v,u){switch(u.index){case 1:s();proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(e).click(function(){jQuery(o).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check", secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0)));jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:false});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:false});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var e=this,d="",f="";if(a.params.title!=null){d=a.params.title;f=this.truncateTitle(d)}jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",d);d="";if(a.params.year)d=a.params.year;else if(a.params.date)if(f=a.params.date.match(/^([12]\d{3})/))d=f[1];var g="";if(a.params.author)g= a.params.author;else if(a.params.last)g=a.params.last;if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="";f=a.type;switch(f){case "web":j=a.params.url;break;case "book":if(a.params.isbn!=null)j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn;break;case "journal":case "conference":if(a.params.doi!=null)j="http://dx.doi.org/"+a.params.doi;break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";if(g!="")i='By: <span class="author">'+g+"</span>";if(d!="")h='Date: <span class="date">'+d+"</span>";if(f!=null){if(j!="")f='<a href="'+j+'" target="_blank">'+f+"</a>";k='Type: <span class="type">'+f+"</span>"}g="";if(f=="raw")g=k+" | "+a.toString();else if(i!="")g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i;else if(h!="")g=k!=""?h+" | "+k:h;else if(k!="")g=k;g="<p>"+g+"</p>";d=jQuery("<div />", {"class":"expanded"});jQuery(d).append(g);jQuery("td.title",b).append(d);if(!c){f=jQuery("#refs tr").length;jQuery("td.number",b).text(f);jQuery("#numRefs").text(f)}jQuery(b).click(function(){e.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});f=function(){e.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()};var l=a.getCitationStrings();g=jQuery('<span class="all-citations" />');for(j=0;j<l.length;j++){i=j+1;for(h="";i> 0;){k=--i%26;h=String.fromCharCode(97+k)+h;i=Math.floor(i/26)}i=jQuery('<a href="#">'+h+"</a>");h=function(o){return function(){var m=0,n=0,p=proveit.getMWEditValue();for(n=0;n<o;n++){m=p.indexOf(l[n],m);if(m==-1){proveit.log("citationStrings["+n+"]: "+l[n]+" not found. Returning.");return false}m+=l[n].length}m=p.indexOf(l[o],m);m==-1?proveit.log("citationStrings["+o+"]: "+l[o]+" not found."):proveit.highlightLengthAtIndex(m,l[o].length);return false}}(j);i.click(h);g.append(i)}if(l.length>1){j= jQuery("<p />");j.append('This reference is cited in the article <span class="num-citations">'+l.length+" times</span>: ").append(g);d.append(j)}if(a.type!="raw"){g=jQuery("<button />",{text:"edit"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:false});g.click(f);jQuery(".edit",b).append(g);g=jQuery("<button />",{"class":"edit",text:"edit this reference"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:true});g.click(f);d.append(g);jQuery(b).dblclick(f)}else jQuery(".edit",b).append("&nbsp;"); if(l.length>0){f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"});jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:true});f.click(function(){e.insertRefIntoMWEditBox(a,false);return false});d.append(f)}return b},truncateTitle:function(a){var c=a;if(a.length>86){c=c.substring(0,86);a=c.lastIndexOf(" ");if(a!=-1){c=c.substr(0,a);c+=" ..."}}return c},formatDate:function(a){return a.getFullYear()+"-"+(a.getMonth()<9?"0":"")+(a.getMonth()+1)+"-"+(a.getDate()< 10?"0":"")+a.getDate()},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a,false))}},window.proveit);proveit.CiteReference.getTypes=function(){return["web","book","journal","conference","encyclopedia","news","newsgroup","press release","interview","episode","video"]};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===undefined;proveit.split._nativeSplit=String.prototype.split; proveit.load(); bgpy4zdy1o0fotsqg7co3ar0emmj6t3 360731 360730 2011-02-27T03:01:22Z en>Mattflaschen 0 Deploy commit d33adfe2b26c of ProveIt. 360731 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2010, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit d33adfe2b26c as of 2011-02-27 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",descriptions:{en:{name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date",accessdate:"Access date", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN",pmid:"PMID", chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL",archivedate:"Date archived", episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID",months:["January","February","March", "April","May","June","July","August","September","October","November","December"]}},getDescriptions:function(){return this.descriptions[proveit.LANG]},log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace==""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var b=0,c=0;do{b+=a.offsetLeft;c+=a.offsetTop}while(a=a.offsetParent); return{left:b,top:c}},highlightLengthAtIndex:function(a,b){if(a<0||b<0)this.log("highlightStringAtIndex: invalid negative arguments");var c=this.getMWEditBox(),d=c.value,e=this.getPosition(c).top;c.value=d.substring(0,a);c.focus();c.scrollTop=1E6;e=c.scrollTop;c.value+=d.substring(a);if(e>0)c.scrollTop=e+this.HALF_EDIT_BOX_HEIGHT;jQuery(c).focus().textSelection("setSelection",{start:a,end:a+b});e=this.getPosition(c).top;window.scroll(0,e);return true},highlightTargetString:function(a){var b=this.getMWEditValue().indexOf(a); if(b==-1){this.log('Target string "'+a+'" not found.');return false}return this.highlightLengthAtIndex(b,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]},getMWEditValue:function(){var a=this.getMWEditBox(),b=a.value;if(!a.selectionStart&&document.selection)b=b.replace(/\r\n/g,"\n");return b},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var b=this.getMWEditForm();if(!b)throw Error("No edit form, possibly due to protected page.");b.addEventListener("submit", a,false)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:false,shouldAddSummary:true,loadMaximized:false,includeProveItEditSummary:function(){if(this.shouldAddSummary&&!this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var c=a.getEditSummary();if(c.value.indexOf("ProveIt")==-1)c.value+=" (edited with [[User:ProveIt_GT|ProveIt]])"});this.summaryFunctionAdded=true}catch(b){this.log("Failed to add onsubmit handler. e.message: "+b.message)}},load:function(){this.summaryFunctionAdded= false;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return true},clearRefBox:function(){var a=this.getRefBox();if(a==null){this.log("Ref box is not loaded yet.");return false}a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,b){var c=this.getMWEditBox();if(!c){this.log("insertRefIntoMWEditBox: txtarea is null");return false}c=jQuery(c);var d=a.getInsertionText(b);c.textSelection("encapsulateSelection", {peri:d,replace:true});c=c.textSelection("getCaretPosition",{startAndEnd:true});this.highlightLengthAtIndex(c[0],c[1]-c[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a,b){var c=jQuery("div.input-row",b),d=jQuery("#editrefname").val();a.name=d!=""?d:null;a.params={};var e,f;for(d=0;d<c.length;d++){e=c[d];f=jQuery(".paramvalue",e)[0];e=jQuery(e).hasClass("addedrow")?jQuery(".paramdesc",e)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length);this.log("paramName: "+e); f=f.value.trim();this.log("paramVal: "+f);if(e!=""&&f!="")a.params[e]=f}if(a.toString()!=a.orig)a.save=false;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var b=this.makeRefBoxRow(a,true),c=jQuery(".selected",this.getRefBox()).get(0);this.log("newRichItem: "+b+", oldRichItem: "+c+"oldRichItem.parentNode: "+c.parentNode);var d=jQuery("td.number",c).text();jQuery("td.number",b).text(d);c.parentNode.replaceChild(b,c);jQuery(b).addClass("selected");a.updateInText();this.includeProveItEditSummary()}}, updateEditPane:function(a){jQuery("#editrefname").val(a.name||"");var b={},c;for(c in a.params)b[c]=a.params[c];var d=a.getDefaultParams();for(c=0;c<d.length;c++)b[d[c]]||(b[d[c]]="");d=a.getRequiredParams();var e=[],f;for(f in b)e.push(f);(f=a.getSorter())?e.sort(f):e.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(c=0;c<e.length;c++)this.addPaneRow(jQuery("#edit-pane").get(),b,this.getDescriptions(),e[c],d[e[c]],true);var g=jQuery("#edit-buttons .accept"), i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a,jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide();jQuery("#view-pane").show()};setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,b,c,d,e,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0), j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);if(e){jQuery(i).addClass("required");jQuery(".delete-field",g).remove()}else this.activateRemoveField(g);if(f){i.attr("for",this.EDIT_PARAM_PREFIX+d);j.attr("id",this.EDIT_PARAM_PREFIX+d);a=c[d];if(!a){this.log("Undefined description for param: "+d+". Using directly as description.");a=d}jQuery(i).text(a);jQuery(i).attr("title",d);jQuery(j).val(b[d]);jQuery(g).show()}else{jQuery(g).show("highlight",{},"slow");jQuery(".inputs",a).scrollTop(1E5)}}, togglestyle:true,toggleinsert:false,split:function(a,b,c){if(Object.prototype.toString.call(b)!=="[object RegExp]")return proveit.split._nativeSplit.call(a,b,c);var d=[],e=0,f=(b.ignoreCase?"i":"")+(b.multiline?"m":"")+(b.sticky?"y":"");b=RegExp(b.source,f+"g");var g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+b.source+"$(?!\\s)",f));if(c===undefined||+c<0)c=Infinity;else{c=Math.floor(+c);if(!c)return[]}for(;i=b.exec(a);){f=i.index+i[0].length;if(f>e){d.push(a.slice(e,i.index));!proveit.split._compliantExecNpcg&& i.length>1&&i[0].replace(g,function(){for(var h=1;h<arguments.length-2;h++)if(arguments[h]===undefined)i[h]=undefined});i.length>1&&i.index<a.length&&Array.prototype.push.apply(d,i.slice(1));j=i[0].length;e=f;if(d.length>=c)break}b.lastIndex===i.index&&b.lastIndex++}if(e===a.length){if(j||!b.test(""))d.push("")}else d.push(a.slice(e));return d.length>c?d.slice(0,c):d},splitNameVals:function(a){var b={};b.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); b.names.length--;b.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return b},scanForRefs:function(){this.log("Entering scanForRefs.");this.clearRefBox();var a=this.getMWEditValue(),b,c={},d=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var e=0;e<a.length;e++){var f=this.makeRef(a[e]);if(f)(b=f.name)||d.push(f);else b=(b=a[e].match(this.REF_REGEX))&&(b[1]||b[2]||b[3]);if(b){if(!c[b]){c[b]={};if(!c[b].strings)c[b].strings= []}if(f&&!c[b].reference){c[b].reference=f;d.push(f)}c[b].strings.push(a[e])}}for(a=0;a<d.length;a++){d[a].name&&d[a].setCitationStrings(c[d[a].name].strings);this.addNewElement(d[a])}},REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var b=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+b);if(!b)return null;b=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)? this.CitationReference:this.RawReference;if(b!=this.RawReference){var c=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],d=a.match(this.REF_REGEX);if(d&&d!=null)var e=d[1]||d[2]||d[3];d=c.split(/\|/g);if(b==this.CiteReference){var f=d[0].toLowerCase().indexOf("e"),g=d[0].indexOf("}");f=d[0].substring(f+1,g!=-1?g:d[0].length).trim()}}a=new b({name:e,type:f,save:true,inMWEditBox:true,orig:a});if(b!=this.RawReference){b=this.splitNameVals(c);c=b.names;b=b.values;for(e=0;e<c.length;e++){d=c[e].trim().replace(/(?:\s*\|)*(.*)/, "$1");f=b[e].trim();if(f!="")a.params[d]=f}}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(b){this.type=b};this.update=function(){var b=this.toString(),c=this.getCitationStrings();if(c.length>0)for(var d=0;d<c.length;d++){if(c[d]==this.orig){proveit.log("Updating "+c[d]+" to "+b);c[d]=b}}else if(this.name!=null){proveit.log("Adding "+b+" to citationStrings");c.push(b)}};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox; this.orig=a.orig;this.params={};this.getSorter=function(){var b=this;return function(c,d){var e=b.getSortIndex(c),f=b.getSortIndex(d);return e!=-1&&f!=-1?e-f:c<d?-1:c==d?0:1}};this.isValid=function(){return true};this.getLabel=function(){var b="";if(this.params.author)b=this.params.author+"; ";else if(this.params.last){b=this.params.last;if(this.params.first)b+=", "+this.params.first;b+="; "}if(this.params.title)b+=this.params.title;if(b==""){for(var c in this.params)break;if(c)b=c}return b};this.getInsertionText= function(b){proveit.log("getInsertionText");if(b)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null");};this.updateInText=function(){var b=proveit.getMWEditBox();if(!(!b||b==null)){b.focus();var c=proveit.getMWEditValue();c=c.replace(this.orig,this.toString());b.value=c;this.orig=this.toString();this.save=true;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(b,c){var d=this.name?'<ref name="'+ this.name+'">':"<ref>";d+="{{"+b+(c?" "+this.type:"");for(var e in this.params)d+=" | "+e+"="+this.params[e];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(b){this.citationStrings=b};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var b={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news",newsgroup:"newsgroup", paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(g){var i=b[g];this.type=i!=null?i:g};proveit.AbstractReference.call(this,a);this.getSortIndex=function(g){return jQuery.inArray(g,["url","title","accessdate","author","last","first","subject","subjectlink","inventor","editor","author2","last2","first2","subject2","subjectlink2","author3","last3","first3","subject3","subjectlink3","author4","last4", "first4","subject4","author5","last5","first5","author6","last6","first6","author7","last7","first7","author8","last8","first8","author9","last9","first9","authorlink","coauthors","interviewer","cointerviewers","type","encyclopedia","newsgroup","journal","booktitle","program","episodelink","series","serieslink","credits","network","station","callsign","city","airdate","began","ended","season","seriesno","number","minutes","transcript","transcripturl","people","date","year","month","article","contribution", "format","medium","newspaper","conference","work","volume","edition","issue","publisher","location","pages","page","language","isbn","issn","oclc","doi","pmid","id","archiveurl","archivedate","time","quote","ref"])};this.toString=function(){return this.toStringInternal("cite",true)};var c={web:{url:true,title:true},book:{title:true},journal:{title:true},conference:{title:true},encyclopedia:{title:true,encyclopedia:true},news:{title:true},newsgroup:{title:true},"press release":{title:true},interview:{last:true}, episode:{title:true},video:{title:true}};this.getRequiredParams=function(){var g=c[this.type];return g?g:{}};var d={web:["url","title","author","accessdate","work","publisher","date","pages"],book:["title","author","authorlink","year","isbn","publisher","location","pages"],journal:["title","author","journal","volume","issue","year","month","pages","url","doi"],conference:["conference","title","booktitle","author","editor","year","month","url","id","accessdate","location","pages","publisher"],encyclopedia:["title", "encyclopedia","author","editor","accessdate","edition","year","publisher","volume","location","pages"],news:["title","author","url","publisher","date","accessdate","pages"],newsgroup:["title","author","date","newsgroup","id","url","accessdate"],"press release":["title","url","publisher","date","accessdate"],interview:["last","first","subjectlink","interviewer","title","callsign","city","date","program","accessdate"],episode:["title","series","credits","airdate","city","network","season"],video:["people", "date","url","title","medium","location","publisher"]};this.getDefaultParams=function(){var g=d[this.type];return g?g:[]};this.isValid=function(){if(this.type=="")return false;var g=this.getRequiredParams(),i=true,j;for(j in g)if(g[j]){i&=j in this.params;if(!i)break}return i};var e={web:"page_white_world.png",book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png",episode:"television.png",video:"film.png"}, f=this.getIcon;this.getIcon=function(){var g=e[this.type];if(g)return proveit.STATIC_BASE+g;return f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var b={},c={web:["url","author","title","date","accessdate"],news:["author","title","newspaper","url","publication-place","volume","issue","date","pages"],encyclopedia:["author","editor","contribution","title","publisher","place","year","volume","pages"],book:["author","title","publisher","place","year"],journal:["author", "title","journal","volume","issue","year","pages"],patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(d){return["last","first","url","author","editor","contribution","author-link","last2","first2","author2-link","publication-date","inventor","title","issue-date","patent-number","country-code","journal","volume","newspaper","issue","date","publisher","place","year","edition","publication-place","series","version","pages","page","id","isbn","doi","oclc", "accessdate"].indexOf(d)};this.toString=function(){return this.toStringInternal("Citation",false)};this.getRequiredParams=function(){return b};this.getDefaultParams=function(){return this.type?c[this.type]:["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+"raw.png"}},getRefFromAddPane:function(a){var b= a.id;b=new (this.togglestyle?this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:b});var c;a=jQuery(".paramlist",a)[0];for(var d=jQuery("div",a),e=0;e<d.length;e++){c=d[e];this.log("getRefFromAddPane: i: "+e+", paramRow: "+c);var f=jQuery(".paramvalue",c)[0];a=jQuery(c).hasClass("addedrow")?jQuery(".paramdesc",c)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+c.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+ f.refName);this.log("getRefFromAddPane: valueTextbox.id: "+f.id);c=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+c);if(a!=""&&c!="")b.params[a]=c}b.update();this.log("Exiting getRefFromAddPane");return b},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,true);a.save=true;a.inMWEditBox=true},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)},activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight", {},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var b=jQuery(".addpanes",a.parentNode.parentNode).get(0);this.clearCitePanes(b);var c=a.value,d=document.getElementById("dummyCitePane").cloneNode(true);d.id=c;jQuery(".ref-name-row",d).children("input").attr("id","addrefname");jQuery(".ref-name-row",d).children("label").attr("for","addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({}); a.type=c;c=this.getDescriptions();var e=a.getDefaultParams().slice(0);e.sort(a.getSorter());for(var f=0;f<e.length;f++)a.params[e[f]]="";this.log("changeAddPane: newRef: "+a);e=[];for(j in a.params)e.push(j);e.sort(a.getSorter());var g=a.getRequiredParams(),i=jQuery(".paramlist",d)[0];for(f=0;f<e.length;f++){var j=e[f],h;if(c[j]){h=document.getElementById("preloadedparamrow").cloneNode(true);var k=jQuery(".paramdesc",h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h); k.text(c[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else{h=document.getElementById("addedparamrow").cloneNode(true);jQuery(".paramdesc",h)[0].setAttribute("value",j)}h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(d).show();b.insertBefore(d,b.firstChild);this.log("Exiting changeAddPane")}, createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css");var a=jQuery("<div/>",{id:"proveit"}),b=jQuery("<div/>",{id:"tabs"}),c=jQuery("<h1/>"),d=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),e=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png",alt:"ProveIt",height:30,width:118});d.append(e);c.append(d);var f=jQuery("<button/>",{text:"show/hide"});c.append(f);b.append(c); e=jQuery("<ul/>");d=jQuery("<li/>");c=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});c.append("References (");var g=jQuery("<span/>",{id:"numRefs"}).append("0");c.append(g).append(")");d.append(c);e.append(d);g=jQuery("<li/>");d=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(d);e.append(g);b.append(e);var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}});e=jQuery("<div/>",{id:"view-pane"});g=jQuery("<div/>",{"class":"scroll", style:"height: 210px;"});var j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>",{"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);e.append(g);i.append(e);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});e=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll", style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.","class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>",{"class":"paramlist"});e.append(h);e.append(g);k.append(e);var l=jQuery("<div/>",{id:"edit-buttons"});e=jQuery("<button/>", {style:"margin-right: 50px;"}).append("add field");l.append(e);e=jQuery("<span/>",{"class":"required",text:"bold"});l.append(e).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"});l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);b.append(i);k=jQuery("<div/>",{id:"dummyCitePane","class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"})); b.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k);l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);b.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row",style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone()); b.append(h);var o=jQuery("<div/>",{id:"add-tab",css:{display:"none"}});h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"});var m=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}),n=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});m.append(n);var p=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(p.get(0))}}),q=this.CiteReference.getTypes();k=this.getDescriptions();for(l=0;l<q.length;l++)p.append(jQuery("<option/>", {value:q[l],text:k[q[l]]}));m.append(p);h.append(m);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));m=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"});n=n.clone().attr("for","citationmenu");m.append(n);var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}});n=["web","book","journal","encyclopedia","news","patent"];for(q=0;q<n.length;q++)r.append(jQuery("<option/>",{value:n[l],text:k[n[l]]}));m.append(r);h.append(m).append(jQuery("<div/>", {"class":"addpanes",id:"citationpanes",style:"display: none;"}));o.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(e.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone());o.append(h);b.append(o);a.append(b);jQuery(document.body).prepend(a);var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(v,u){switch(u.index){case 1:s(); proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(c).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(d).click(function(){jQuery(o).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check",secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0))); jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:false});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:false});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,b){var c=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(c).addClass("invalid");jQuery(".edit button",c).get(0);var d=this,e="",f="";if(a.params.title!=null){e=a.params.title;f=this.truncateTitle(e)}jQuery("td.title",c).text(f);jQuery("td.title",c).attr("title",e);e="";if(a.params.year)e=a.params.year;else if(a.params.date)if(f=a.params.date.match(/^([12]\d{3})/))e=f[1];var g="";if(a.params.author)g= a.params.author;else if(a.params.last)g=a.params.last;if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="";f=a.type;switch(f){case "web":j=a.params.url;break;case "book":if(a.params.isbn!=null)j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn;break;case "journal":case "conference":if(a.params.doi!=null)j="http://dx.doi.org/"+a.params.doi;break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", c).css("background-image","url("+i+")");jQuery("td.type",c).attr("title",a.type);var h=i="",k="";if(g!="")i='By: <span class="author">'+g+"</span>";if(e!="")h='Date: <span class="date">'+e+"</span>";if(f!=null){if(j!="")f='<a href="'+j+'" target="_blank">'+f+"</a>";k='Type: <span class="type">'+f+"</span>"}g="";if(f=="raw")g=k+" | "+a.toString();else if(i!="")g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i;else if(h!="")g=k!=""?h+" | "+k:h;else if(k!="")g=k;g="<p>"+g+"</p>";e=jQuery("<div />", {"class":"expanded"});jQuery(e).append(g);jQuery("td.title",c).append(e);if(!b){f=jQuery("#refs tr").length;jQuery("td.number",c).text(f);jQuery("#numRefs").text(f)}jQuery(c).click(function(){d.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(c).addClass("selected")});f=function(){d.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()};var l=a.getCitationStrings();g=jQuery('<span class="all-citations" />');for(j=0;j<l.length;j++){i=j+1;for(h="";i> 0;){k=--i%26;h=String.fromCharCode(97+k)+h;i=Math.floor(i/26)}i=jQuery('<a href="#">'+h+"</a>");h=function(o){return function(){var m=0,n=0,p=proveit.getMWEditValue();for(n=0;n<o;n++){m=p.indexOf(l[n],m);if(m==-1){proveit.log("citationStrings["+n+"]: "+l[n]+" not found. Returning.");return false}m+=l[n].length}m=p.indexOf(l[o],m);m==-1?proveit.log("citationStrings["+o+"]: "+l[o]+" not found."):proveit.highlightLengthAtIndex(m,l[o].length);return false}}(j);i.click(h);g.append(i)}if(l.length>1){j= jQuery("<p />");j.append('This reference is cited in the article <span class="num-citations">'+l.length+" times</span>: ").append(g);e.append(j)}if(a.type!="raw"){g=jQuery("<button />",{text:"edit"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:false});g.click(f);jQuery(".edit",c).append(g);g=jQuery("<button />",{"class":"edit",text:"edit this reference"});jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:true});g.click(f);e.append(g);jQuery(c).dblclick(f)}else jQuery(".edit",c).append("&nbsp;"); if(l.length>0){f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"});jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:true});f.click(function(){d.insertRefIntoMWEditBox(a,false);return false});e.append(f)}return c},truncateTitle:function(a){var b=a;if(a.length>86){b=b.substring(0,86);a=b.lastIndexOf(" ");if(a!=-1){b=b.substr(0,a);b+=" ..."}}return b},formatDate:function(a){var b=a.getFullYear(),c=this.getDescriptions().months[a.getMonth()];a=(a.getDate()< 10?"0":"")+a.getDate();return c+" "+a+", "+b},addNewElement:function(a){var b=this.getRefBox();jQuery(b).append(this.makeRefBoxRow(a,false))}},window.proveit);proveit.CiteReference.getTypes=function(){return["web","book","journal","conference","encyclopedia","news","newsgroup","press release","interview","episode","video"]};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===undefined; proveit.split._nativeSplit=String.prototype.split;proveit.load(); ga3boc1l4u79lxslhl6vqrpumnnbxuc 360732 360731 2011-04-12T02:00:29Z en>Mattflaschen 0 Deploy commit 930696884fe7 of ProveIt. 360732 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2011, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit 930696884fe7 as of 2011-04-12 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",descriptions:{en:{name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date",accessdate:"Access date", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN",pmid:"PMID", chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL",archivedate:"Date archived", episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID",months:["January","February","March", "April","May","June","July","August","September","October","November","December"]}},getDescriptions:function(){return this.descriptions[proveit.LANG]},log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace==""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do c+=a.offsetLeft,b+=a.offsetTop;while(a=a.offsetParent); return{left:c,top:b}},highlightLengthAtIndex:function(a,c){(a<0||c<0)&&this.log("highlightStringAtIndex: invalid negative arguments");var b=this.getMWEditBox(),d=b.value,e=this.getPosition(b).top;b.value=d.substring(0,a);b.focus();b.scrollTop=1E6;e=b.scrollTop;b.value+=d.substring(a);if(e>0)b.scrollTop=e+this.HALF_EDIT_BOX_HEIGHT;jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});e=this.getPosition(b).top;window.scroll(0,e);return!0},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a); if(c==-1)return this.log('Target string "'+a+'" not found.'),!1;return this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]},getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;!a.selectionStart&&document.selection&&(c=c.replace(/\r\n/g,"\n"));return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit", a,!1)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:!1,shouldAddSummary:!0,loadMaximized:!1,includeProveItEditSummary:function(){if(this.shouldAddSummary&&!this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var c=a.getEditSummary();c.value.indexOf("ProveIt")==-1&&(c.value+=" (edited with [[User:ProveIt_GT|ProveIt]])")});this.summaryFunctionAdded=!0}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded= !1;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return!0},clearRefBox:function(){var a=this.getRefBox();if(a==null)return this.log("Ref box is not loaded yet."),!1;a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b)return this.log("insertRefIntoMWEditBox: txtarea is null"),!1;var b=jQuery(b),d=a.getInsertionText(c);b.textSelection("encapsulateSelection", {peri:d,replace:!0});b=b.textSelection("getCaretPosition",{startAndEnd:!0});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a,c){var b=jQuery("div.input-row",c),d=jQuery("#editrefname").val();a.name=d!=""?d:null;a.params={};for(var e,f,d=0;d<b.length;d++)e=b[d],f=jQuery(".paramvalue",e)[0],e=jQuery(e).hasClass("addedrow")?jQuery(".paramdesc",e)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length),this.log("paramName: "+e),f=f.value.trim(), this.log("paramVal: "+f),e!=""&&f!=""&&(a.params[e]=f);if(a.toString()!=a.orig)a.save=!1;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a,!0),b=jQuery(".selected",this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var d=jQuery("td.number",b).text();jQuery("td.number",c).text(d);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name|| "");var c={},b;for(b in a.params)c[b]=a.params[b];var d=a.getDefaultParams();for(b=0;b<d.length;b++)c[d[b]]||(c[d[b]]="");var d=a.getRequiredParams(),e=[],f;for(f in c)e.push(f);(f=a.getSorter())?e.sort(f):e.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<e.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,this.getDescriptions(),e[b],d[e[b]],!0);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a, jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide();jQuery("#view-pane").show()};setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,d,e,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);e?(jQuery(i).addClass("required"), jQuery(".delete-field",g).remove()):this.activateRemoveField(g);f?(i.attr("for",this.EDIT_PARAM_PREFIX+d),j.attr("id",this.EDIT_PARAM_PREFIX+d),a=b[d],a||(this.log("Undefined description for param: "+d+". Using directly as description."),a=d),jQuery(i).text(a),jQuery(i).attr("title",d),jQuery(j).val(c[d]),jQuery(g).show()):(jQuery(g).show("highlight",{},"slow"),jQuery(".inputs",a).scrollTop(1E5))},togglestyle:!0,toggleinsert:!1,split:function(a,c,b){if(Object.prototype.toString.call(c)!=="[object RegExp]")return proveit.split._nativeSplit.call(a, c,b);var d=[],e=0,f=(c.ignoreCase?"i":"")+(c.multiline?"m":"")+(c.sticky?"y":""),c=RegExp(c.source,f+"g"),g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(b===void 0||+b<0)b=Infinity;else if(b=Math.floor(+b),!b)return[];for(;i=c.exec(a);){f=i.index+i[0].length;if(f>e&&(d.push(a.slice(e,i.index)),!proveit.split._compliantExecNpcg&&i.length>1&&i[0].replace(g,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===void 0&&(i[a]=void 0)}),i.length>1&&i.index< a.length&&Array.prototype.push.apply(d,i.slice(1)),j=i[0].length,e=f,d.length>=b))break;c.lastIndex===i.index&&c.lastIndex++}e===a.length?(j||!c.test(""))&&d.push(""):d.push(a.slice(e));return d.length>b?d.slice(0,b):d},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs."); this.clearRefBox();var a=this.getMWEditValue(),c,b={},d=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var e=0;e<a.length;e++){var f=this.makeRef(a[e]);f?(c=f.name)||d.push(f):c=(c=a[e].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);if(c){if(!b[c]&&(b[c]={},!b[c].strings))b[c].strings=[];if(f&&!b[c].reference)b[c].reference=f,d.push(f);b[c].strings.push(a[e])}}for(a=0;a<d.length;a++)d[a].name&&d[a].setCitationStrings(b[d[a].name].strings),this.addNewElement(d[a])}, REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],d=a.match(this.REF_REGEX);if(d&&d!=null)var e=d[1]||d[2]||d[3]; d=b.split(/\|/g);if(c==this.CiteReference)var f=d[0].toLowerCase().indexOf("e"),g=d[0].indexOf("}"),f=d[0].substring(f+1,g!=-1?g:d[0].length).trim()}a=new c({name:e,type:f,save:!0,inMWEditBox:!0,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(e=0;e<b.length;e++)d=b[e].trim().replace(/(?:\s*\|)*(.*)/,"$1"),f=c[e].trim(),f!=""&&(a.params[d]=f)}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(a){this.type=a};this.update=function(){var a= this.toString(),b=this.getCitationStrings();if(b.length>0)for(var d=0;d<b.length;d++)b[d]==this.orig&&(proveit.log("Updating "+b[d]+" to "+a),b[d]=a);else this.name!=null&&(proveit.log("Adding "+a+" to citationStrings"),b.push(a))};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};this.getSorter=function(){var a=this;return function(b,d){var e=a.getSortIndex(b),f=a.getSortIndex(d);return e!=-1&&f!=-1?e-f:b<d?-1:b== d?0:1}};this.isValid=function(){return!0};this.getLabel=function(){var a="";if(this.params.author)a=this.params.author+"; ";else if(this.params.last)a=this.params.last,this.params.first&&(a+=", "+this.params.first),a+="; ";this.params.title&&(a+=this.params.title);if(a==""){for(var b in this.params)break;b&&(a=b)}return a};this.getInsertionText=function(a){proveit.log("getInsertionText");if(a)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null"); };this.updateInText=function(){var a=proveit.getMWEditBox();if(a&&a!=null){a.focus();var b=proveit.getMWEditValue(),b=b.replace(this.orig,this.toString());a.value=b;this.orig=this.toString();this.save=!0;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(a,b){var d=this.name?'<ref name="'+this.name+'">':"<ref>";d+="{{"+a+(b?" "+this.type:"");for(var e in this.params)d+=" | "+e+"="+this.params[e];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(a){this.citationStrings= a};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news",newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(a){var b=c[a];this.type=b!=null?b:a};proveit.AbstractReference.call(this, a);this.getSortIndex=function(a){return jQuery.inArray(a,["url","title","encyclopedia","publisher","work","date","accessdate","author","last","first","subject","subjectlink","inventor","editor","author2","last2","first2","subject2","subjectlink2","author3","last3","first3","subject3","subjectlink3","author4","last4","first4","subject4","author5","last5","first5","author6","last6","first6","author7","last7","first7","author8","last8","first8","author9","last9","first9","authorlink","coauthors","interviewer", "cointerviewers","type","newsgroup","journal","booktitle","program","episodelink","series","serieslink","credits","network","station","callsign","city","airdate","began","ended","season","seriesno","number","minutes","transcript","transcripturl","people","year","month","article","contribution","format","medium","newspaper","conference","volume","edition","issue","location","pages","page","language","isbn","issn","oclc","doi","pmid","id","archiveurl","archivedate","time","quote","ref"])};this.toString= function(){return this.toStringInternal("cite",!0)};var b={web:{url:!0,title:!0},book:{title:!0},journal:{title:!0},conference:{title:!0},encyclopedia:{title:!0,encyclopedia:!0},news:{title:!0,work:!0,date:!0},newsgroup:{title:!0},"press release":{title:!0},interview:{last:!0},episode:{title:!0},video:{title:!0}};this.getRequiredParams=function(){var a=b[this.type];return a?a:{}};var d={web:["url","title","author","accessdate","work","publisher","date","pages"],book:["title","author","authorlink", "year","isbn","publisher","location","pages"],journal:["title","author","journal","volume","issue","year","month","pages","url","doi"],conference:["conference","title","booktitle","author","editor","year","month","url","id","accessdate","location","pages","publisher"],encyclopedia:["title","encyclopedia","author","editor","accessdate","edition","year","publisher","volume","location","pages"],news:["title","author","url","work","date","accessdate","pages","location"],newsgroup:["title","author","date", "newsgroup","id","url","accessdate"],"press release":["title","url","publisher","date","accessdate"],interview:["last","first","subjectlink","interviewer","title","callsign","city","date","program","accessdate"],episode:["title","series","credits","airdate","city","network","season"],video:["people","date","url","title","medium","location","publisher"]};this.getDefaultParams=function(){var a=d[this.type];return a?a:[]};this.isValid=function(){if(this.type=="")return!1;var a=this.getRequiredParams(), b=!0,c;for(c in a)if(a[c]&&(b&=c in this.params,!b))break;return b};var e={web:"page_white_world.png",book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png",episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var a=e[this.type];if(a)return proveit.STATIC_BASE+a;return f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url", "author","title","date","accessdate"],news:["author","title","newspaper","url","publication-place","volume","issue","date","pages"],encyclopedia:["author","editor","contribution","title","publisher","place","year","volume","pages"],book:["author","title","publisher","place","year"],journal:["author","title","journal","volume","issue","year","pages"],patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(a){return["last","first","url","author","editor", "contribution","author-link","last2","first2","author2-link","publication-date","inventor","title","issue-date","patent-number","country-code","journal","volume","newspaper","issue","date","publisher","place","year","edition","publication-place","series","version","pages","page","id","isbn","doi","oclc","accessdate"].indexOf(a)};this.toString=function(){return this.toStringInternal("Citation",!1)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]: ["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+"raw.png"}},getRefFromAddPane:function(a){for(var c=a.id,c=new (this.togglestyle?this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c}),b,a=jQuery(".paramlist",a)[0],d=jQuery("div",a),e=0;e<d.length;e++){b=d[e];this.log("getRefFromAddPane: i: "+ e+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0],a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName);this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);a!=""&&b!=""&&(c.params[a]=b)}c.update();this.log("Exiting getRefFromAddPane"); return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,!0);a.save=!0;a.inMWEditBox=!0},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)},activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight",{},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0); this.clearCitePanes(c);var b=a.value,d=document.getElementById("dummyCitePane").cloneNode(!0);d.id=b.replace(" ","_");jQuery(".ref-name-row",d).children("input").attr("id","addrefname");jQuery(".ref-name-row",d).children("label").attr("for","addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({});a.type=b;var b=this.getDescriptions(),e=a.getDefaultParams().slice(0);e.sort(a.getSorter());for(var f=0;f<e.length;f++)a.params[e[f]]="";this.log("changeAddPane: newRef: "+ a);e=[];for(j in a.params)e.push(j);e.sort(a.getSorter());for(var g=a.getRequiredParams(),i=jQuery(".paramlist",d)[0],f=0;f<e.length;f++){var j=e[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(!0);var k=jQuery(".paramdesc",h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h);k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else h= document.getElementById("addedparamrow").cloneNode(!0),jQuery(".paramdesc",h)[0].setAttribute("value",j);h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(d).show();c.insertBefore(d,c.firstChild);this.log("Exiting changeAddPane")},createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css"); var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),d=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),e=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png",alt:"ProveIt",height:30,width:118});d.append(e);b.append(d);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b);e=jQuery("<ul/>");d=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References ("); var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");d.append(b);e.append(d);g=jQuery("<li/>");d=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(d);e.append(g);c.append(e);var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}}),e=jQuery("<div/>",{id:"view-pane"}),g=jQuery("<div/>",{"class":"scroll",style:"height: 210px;"}),j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>", {"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);e.append(g);i.append(e);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});e=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll",style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.", "class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>",{"class":"paramlist"});e.append(h);e.append(g);k.append(e);var l=jQuery("<div/>",{id:"edit-buttons"}),e=jQuery("<button/>",{style:"margin-right: 50px;"}).append("add field");l.append(e);e=jQuery("<span/>",{"class":"required",text:"bold"});l.append(e).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"}); l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane","class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"}));c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k); l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row",style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone());c.append(h);var p=jQuery("<div/>",{id:"add-tab",css:{display:"none"}}),h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"}),n=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}), m=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});n.append(m);for(var q=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(q.get(0))}}),o=this.CiteReference.getTypes(),k=this.getDescriptions(),l=0;l<o.length;l++)q.append(jQuery("<option/>",{value:o[l],text:k[o[l]]}));n.append(q);h.append(n);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));n=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"}); m=m.clone().attr("for","citationmenu");n.append(m);for(var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}}),m=["web","book","journal","encyclopedia","news","patent"],o=0;o<m.length;o++)r.append(jQuery("<option/>",{value:m[l],text:k[m[l]]}));n.append(r);h.append(n).append(jQuery("<div/>",{"class":"addpanes",id:"citationpanes",style:"display: none;"}));p.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(e.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone()); p.append(h);c.append(p);a.append(c);jQuery(document.body).prepend(a);var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(a,b){switch(b.index){case 1:s(),proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(d).click(function(){jQuery(p).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check", secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0)));jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:!1});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:!1});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var d=this,e="",f="";if(a.params.title!=null)e=a.params.title,f=this.truncateTitle(e);jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",e);e="";a.params.year?e=a.params.year:a.params.date&&(f=a.params.date.match(/^([12]\d{3})/))&&(e=f[1]);var g="";a.params.author? g=a.params.author:a.params.last&&(g=a.params.last);if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="",f=a.type;switch(f){case "web":j=a.params.url;break;case "book":a.params.isbn!=null&&(j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn);break;case "journal":case "conference":a.params.doi!=null&&(j="http://dx.doi.org/"+a.params.doi);break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";g!=""&&(i='By: <span class="author">'+g+"</span>");e!=""&&(h='Date: <span class="date">'+e+"</span>");f!=null&&(j!=""&&(f='<a href="'+j+'" target="_blank">'+f+"</a>"),k='Type: <span class="type">'+f+"</span>");g="";f=="raw"?g=k+" | "+a.toString():i!=""?g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i:h!=""?g=k!=""?h+" | "+k:h:k!=""&&(g=k);g="<p>"+g+"</p>";e=jQuery("<div />",{"class":"expanded"}); jQuery(e).append(g);jQuery("td.title",b).append(e);if(!c)f=jQuery("#refs tr").length,jQuery("td.number",b).text(f),jQuery("#numRefs").text(f);jQuery(b).click(function(){d.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});for(var f=function(){d.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()},l=a.getCitationStrings(),g=jQuery('<span class="all-citations" />'),j=0;j<l.length;j++){i=j+1;for(h="";i>0;)k=--i%26,h=String.fromCharCode(97+ k)+h,i=Math.floor(i/26);i=jQuery('<a href="#">'+h+"</a>");h=function(a){return function(){for(var b=0,c=0,d=proveit.getMWEditValue(),c=0;c<a;c++){b=d.indexOf(l[c],b);if(b==-1)return proveit.log("citationStrings["+c+"]: "+l[c]+" not found. Returning."),!1;b+=l[c].length}b=d.indexOf(l[a],b);b==-1?proveit.log("citationStrings["+a+"]: "+l[a]+" not found."):proveit.highlightLengthAtIndex(b,l[a].length);return!1}}(j);i.click(h);g.append(i)}l.length>1&&(j=jQuery("<p />"),j.append('This reference is cited in the article <span class="num-citations">'+ l.length+" times</span>: ").append(g),e.append(j));a.type!="raw"?(g=jQuery("<button />",{text:"edit"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!1}),g.click(f),jQuery(".edit",b).append(g),g=jQuery("<button />",{"class":"edit",text:"edit this reference"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!0}),g.click(f),e.append(g),jQuery(b).dblclick(f)):jQuery(".edit",b).append("&nbsp;");l.length>0&&(f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"}), jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:!0}),f.click(function(){d.insertRefIntoMWEditBox(a,!1);return!1}),e.append(f));return b},truncateTitle:function(a){var c=a;a.length>86&&(c=c.substring(0,86),a=c.lastIndexOf(" "),a!=-1&&(c=c.substr(0,a),c+=" ..."));return c},formatDate:function(a){var c=a.getFullYear(),b=this.getDescriptions().months[a.getMonth()],a=(a.getDate()<10?"0":"")+a.getDate();return b+" "+a+", "+c},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a, !1))}},window.proveit);proveit.CiteReference.getTypes=function(){return["web","book","journal","conference","encyclopedia","news","newsgroup","press release","interview","episode","video"]};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===void 0;proveit.split._nativeSplit=String.prototype.split;proveit.load(); 3tcudptevm8cvk55o9ed4oz7y57bbr9 360733 360732 2011-06-17T03:31:16Z en>Mattflaschen 0 Deploy commit 5df6c719a13d of ProveIt. 360733 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2011, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit 5df6c719a13d as of 2011-06-17 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",descriptions:{en:{agency:"Agency",name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date",accessdate:"Access date", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN",pmid:"PMID", chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL",archivedate:"Date archived", episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID",months:["January","February","March", "April","May","June","July","August","September","October","November","December"]}},getDescriptions:function(){return this.descriptions[proveit.LANG]},log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace==""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do c+=a.offsetLeft,b+=a.offsetTop;while(a=a.offsetParent); return{left:c,top:b}},highlightLengthAtIndex:function(a,c){(a<0||c<0)&&this.log("highlightStringAtIndex: invalid negative arguments");var b=this.getMWEditBox(),d=b.value,e=this.getPosition(b).top;b.value=d.substring(0,a);b.focus();b.scrollTop=1E6;e=b.scrollTop;b.value+=d.substring(a);if(e>0)b.scrollTop=e+this.HALF_EDIT_BOX_HEIGHT;jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});e=this.getPosition(b).top;window.scroll(0,e);return!0},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a); if(c==-1)return this.log('Target string "'+a+'" not found.'),!1;return this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]},getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;!a.selectionStart&&document.selection&&(c=c.replace(/\r\n/g,"\n"));return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit", a,!1)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:!1,shouldAddSummary:!0,loadMaximized:!1,includeProveItEditSummary:function(){if(this.shouldAddSummary&&!this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var c=a.getEditSummary();c.value.indexOf("ProveIt")==-1&&(c.value+=" (edited with [[User:ProveIt_GT|ProveIt]])")});this.summaryFunctionAdded=!0}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded= !1;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return!0},clearRefBox:function(){var a=this.getRefBox();if(a==null)return this.log("Ref box is not loaded yet."),!1;a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b)return this.log("insertRefIntoMWEditBox: txtarea is null"),!1;var b=jQuery(b),d=a.getInsertionText(c);b.textSelection("encapsulateSelection", {peri:d,replace:!0});b=b.textSelection("getCaretPosition",{startAndEnd:!0});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a,c){var b=jQuery("div.input-row",c),d=jQuery("#editrefname").val();a.name=d!=""?d:null;a.params={};for(var e,f,d=0;d<b.length;d++)e=b[d],f=jQuery(".paramvalue",e)[0],e=jQuery(e).hasClass("addedrow")?jQuery(".paramdesc",e)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length),this.log("paramName: "+e),f=f.value.trim(), this.log("paramVal: "+f),e!=""&&f!=""&&(a.params[e]=f);if(a.toString()!=a.orig)a.save=!1;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a,!0),b=jQuery(".selected",this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var d=jQuery("td.number",b).text();jQuery("td.number",c).text(d);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name|| "");var c={},b;for(b in a.params)c[b]=a.params[b];var d=a.getDefaultParams();for(b=0;b<d.length;b++)c[d[b]]||(c[d[b]]="");var d=a.getRequiredParams(),e=[],f;for(f in c)e.push(f);(f=a.getSorter())?e.sort(f):e.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<e.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,this.getDescriptions(),e[b],d[e[b]],!0);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a, jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide();jQuery("#view-pane").show()};setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,d,e,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);e?(jQuery(i).addClass("required"), jQuery(".delete-field",g).remove()):this.activateRemoveField(g);f?(i.attr("for",this.EDIT_PARAM_PREFIX+d),j.attr("id",this.EDIT_PARAM_PREFIX+d),a=b[d],a||(this.log("Undefined description for param: "+d+". Using directly as description."),a=d),jQuery(i).text(a),jQuery(i).attr("title",d),jQuery(j).val(c[d]),jQuery(g).show()):(jQuery(g).show("highlight",{},"slow"),jQuery(".inputs",a).scrollTop(1E5))},togglestyle:!0,toggleinsert:!1,split:function(a,c,b){if(Object.prototype.toString.call(c)!=="[object RegExp]")return proveit.split._nativeSplit.call(a, c,b);var d=[],e=0,f=(c.ignoreCase?"i":"")+(c.multiline?"m":"")+(c.sticky?"y":""),c=RegExp(c.source,f+"g"),g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(b===void 0||+b<0)b=Infinity;else if(b=Math.floor(+b),!b)return[];for(;i=c.exec(a);){f=i.index+i[0].length;if(f>e&&(d.push(a.slice(e,i.index)),!proveit.split._compliantExecNpcg&&i.length>1&&i[0].replace(g,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===void 0&&(i[a]=void 0)}),i.length>1&&i.index< a.length&&Array.prototype.push.apply(d,i.slice(1)),j=i[0].length,e=f,d.length>=b))break;c.lastIndex===i.index&&c.lastIndex++}e===a.length?(j||!c.test(""))&&d.push(""):d.push(a.slice(e));return d.length>b?d.slice(0,b):d},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs."); this.clearRefBox();var a=this.getMWEditValue(),c,b={},d=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var e=0;e<a.length;e++){var f=this.makeRef(a[e]);f?(c=f.name)||d.push(f):c=(c=a[e].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);if(c){if(!b[c]&&(b[c]={},!b[c].strings))b[c].strings=[];if(f&&!b[c].reference)b[c].reference=f,d.push(f);b[c].strings.push(a[e])}}for(a=0;a<d.length;a++)d[a].name&&d[a].setCitationStrings(b[d[a].name].strings),this.addNewElement(d[a])}, REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],d=a.match(this.REF_REGEX);if(d&&d!=null)var e=d[1]||d[2]||d[3]; d=b.split(/\|/g);if(c==this.CiteReference)var f=d[0].toLowerCase().indexOf("e"),g=d[0].indexOf("}"),f=d[0].substring(f+1,g!=-1?g:d[0].length).trim()}a=new c({name:e,type:f,save:!0,inMWEditBox:!0,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(e=0;e<b.length;e++)d=b[e].trim().replace(/(?:\s*\|)*(.*)/,"$1"),f=c[e].trim(),f!=""&&(a.params[d]=f)}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(a){this.type=a};this.update=function(){var a= this.toString(),b=this.getCitationStrings();if(b.length>0)for(var d=0;d<b.length;d++)b[d]==this.orig&&(proveit.log("Updating "+b[d]+" to "+a),b[d]=a);else this.name!=null&&(proveit.log("Adding "+a+" to citationStrings"),b.push(a))};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};this.getSorter=function(){var a=this;return function(b,d){var e=a.getSortIndex(b),f=a.getSortIndex(d);return e!=-1&&f!=-1?e-f:b<d?-1:b== d?0:1}};this.isValid=function(){return!0};this.getLabel=function(){var a="";if(this.params.author)a=this.params.author+"; ";else if(this.params.last)a=this.params.last,this.params.first&&(a+=", "+this.params.first),a+="; ";this.params.title&&(a+=this.params.title);if(a==""){for(var b in this.params)break;b&&(a=b)}return a};this.getInsertionText=function(a){proveit.log("getInsertionText");if(a)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null"); };this.updateInText=function(){var a=proveit.getMWEditBox();if(a&&a!=null){a.focus();var b=proveit.getMWEditValue(),b=b.replace(this.orig,this.toString());a.value=b;this.orig=this.toString();this.save=!0;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(a,b){var d=this.name?'<ref name="'+this.name+'">':"<ref>";d+="{{"+a+(b?" "+this.type:"");for(var e in this.params)d+=" | "+e+"="+this.params[e];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(a){this.citationStrings= a};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news",newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(a){var b=c[a];this.type=b!=null?b:a};proveit.AbstractReference.call(this, a);this.getSortIndex=function(a){return jQuery.inArray(a,["url","title","encyclopedia","publisher","work","date","agency","accessdate","author","last","first","subject","subjectlink","inventor","editor","author2","last2","first2","subject2","subjectlink2","author3","last3","first3","subject3","subjectlink3","author4","last4","first4","subject4","author5","last5","first5","author6","last6","first6","author7","last7","first7","author8","last8","first8","author9","last9","first9","authorlink","coauthors", "interviewer","cointerviewers","type","newsgroup","journal","booktitle","program","episodelink","series","serieslink","credits","network","station","callsign","city","airdate","began","ended","season","seriesno","number","minutes","transcript","transcripturl","people","year","month","article","contribution","format","medium","newspaper","conference","volume","edition","issue","location","pages","page","language","isbn","issn","oclc","doi","pmid","id","archiveurl","archivedate","time","quote","ref"])}; this.toString=function(){return this.toStringInternal("cite",!0)};var b={web:{url:!0,title:!0},book:{title:!0},journal:{title:!0},conference:{title:!0},encyclopedia:{title:!0,encyclopedia:!0},news:{title:!0,work:!0,date:!0},newsgroup:{title:!0},"press release":{title:!0},interview:{last:!0},episode:{title:!0},video:{title:!0}};this.getRequiredParams=function(){var a=b[this.type];return a?a:{}};var d={web:["url","title","author","accessdate","work","publisher","date","pages"],book:["title","author", "authorlink","year","isbn","publisher","location","pages"],journal:["title","author","journal","volume","issue","year","month","pages","url","doi"],conference:["conference","title","booktitle","author","editor","year","month","url","id","accessdate","location","pages","publisher"],encyclopedia:["title","encyclopedia","author","editor","accessdate","edition","year","publisher","volume","location","pages"],news:["title","author","url","work","date","accessdate","pages","location","agency"],newsgroup:["title", "author","date","newsgroup","id","url","accessdate"],"press release":["title","url","publisher","date","accessdate"],interview:["last","first","subjectlink","interviewer","title","callsign","city","date","program","accessdate"],episode:["title","series","credits","airdate","city","network","season"],video:["people","date","url","title","medium","location","publisher"]};this.getDefaultParams=function(){var a=d[this.type];return a?a:[]};this.isValid=function(){if(this.type=="")return!1;var a=this.getRequiredParams(), b=!0,c;for(c in a)if(a[c]&&(b&=c in this.params,!b))break;return b};var e={web:"page_white_world.png",book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png",episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var a=e[this.type];if(a)return proveit.STATIC_BASE+a;return f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url", "author","title","date","accessdate"],news:["author","title","newspaper","url","publication-place","volume","issue","date","pages"],encyclopedia:["author","editor","contribution","title","publisher","place","year","volume","pages"],book:["author","title","publisher","place","year"],journal:["author","title","journal","volume","issue","year","pages"],patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(a){return["last","first","url","author","editor", "contribution","author-link","last2","first2","author2-link","publication-date","inventor","title","issue-date","patent-number","country-code","journal","volume","newspaper","issue","date","publisher","place","year","edition","publication-place","series","version","pages","page","id","isbn","doi","oclc","accessdate"].indexOf(a)};this.toString=function(){return this.toStringInternal("Citation",!1)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]: ["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+"raw.png"}},getRefFromAddPane:function(a){for(var c=a.id,c=new (this.togglestyle?this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c}),b,a=jQuery(".paramlist",a)[0],d=jQuery("div",a),e=0;e<d.length;e++){b=d[e];this.log("getRefFromAddPane: i: "+ e+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0],a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName);this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);a!=""&&b!=""&&(c.params[a]=b)}c.update();this.log("Exiting getRefFromAddPane"); return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,!0);a.save=!0;a.inMWEditBox=!0},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)},activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight",{},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0); this.clearCitePanes(c);var b=a.value,d=document.getElementById("dummyCitePane").cloneNode(!0);d.id=b.replace(" ","_");jQuery(".ref-name-row",d).children("input").attr("id","addrefname");jQuery(".ref-name-row",d).children("label").attr("for","addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({});a.type=b;var b=this.getDescriptions(),e=a.getDefaultParams().slice(0);e.sort(a.getSorter());for(var f=0;f<e.length;f++)a.params[e[f]]="";this.log("changeAddPane: newRef: "+ a);e=[];for(j in a.params)e.push(j);e.sort(a.getSorter());for(var g=a.getRequiredParams(),i=jQuery(".paramlist",d)[0],f=0;f<e.length;f++){var j=e[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(!0);var k=jQuery(".paramdesc",h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h);k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else h= document.getElementById("addedparamrow").cloneNode(!0),jQuery(".paramdesc",h)[0].setAttribute("value",j);h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(d).show();c.insertBefore(d,c.firstChild);this.log("Exiting changeAddPane")},createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css"); var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),d=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),e=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png",alt:"ProveIt",height:30,width:118});d.append(e);b.append(d);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b);e=jQuery("<ul/>");d=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References ("); var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");d.append(b);e.append(d);g=jQuery("<li/>");d=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(d);e.append(g);c.append(e);var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}}),e=jQuery("<div/>",{id:"view-pane"}),g=jQuery("<div/>",{"class":"scroll",style:"height: 210px;"}),j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>", {"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);e.append(g);i.append(e);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});e=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll",style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.", "class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>",{"class":"paramlist"});e.append(h);e.append(g);k.append(e);var l=jQuery("<div/>",{id:"edit-buttons"}),e=jQuery("<button/>",{style:"margin-right: 50px;"}).append("add field");l.append(e);e=jQuery("<span/>",{"class":"required",text:"bold"});l.append(e).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"}); l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane","class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"}));c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k); l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row",style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone());c.append(h);var p=jQuery("<div/>",{id:"add-tab",css:{display:"none"}}),h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"}),n=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}), m=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});n.append(m);for(var q=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(q.get(0))}}),o=this.CiteReference.getTypes(),k=this.getDescriptions(),l=0;l<o.length;l++)q.append(jQuery("<option/>",{value:o[l],text:k[o[l]]}));n.append(q);h.append(n);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));n=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"}); m=m.clone().attr("for","citationmenu");n.append(m);for(var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}}),m=["web","book","journal","encyclopedia","news","patent"],o=0;o<m.length;o++)r.append(jQuery("<option/>",{value:m[l],text:k[m[l]]}));n.append(r);h.append(n).append(jQuery("<div/>",{"class":"addpanes",id:"citationpanes",style:"display: none;"}));p.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(e.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone()); p.append(h);c.append(p);a.append(c);jQuery(document.body).prepend(a);var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(a,b){switch(b.index){case 1:s(),proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(d).click(function(){jQuery(p).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check", secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0)));jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:!1});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:!1});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var d=this,e="",f="";if(a.params.title!=null)e=a.params.title,f=this.truncateTitle(e);jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",e);e="";a.params.year?e=a.params.year:a.params.date&&(f=a.params.date.match(/^([12]\d{3})/))&&(e=f[1]);var g="";a.params.author? g=a.params.author:a.params.last&&(g=a.params.last);if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="",f=a.type;switch(f){case "web":j=a.params.url;break;case "book":a.params.isbn!=null&&(j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn);break;case "journal":case "conference":a.params.doi!=null&&(j="http://dx.doi.org/"+a.params.doi);break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";g!=""&&(i='By: <span class="author">'+g+"</span>");e!=""&&(h='Date: <span class="date">'+e+"</span>");f!=null&&(j!=""&&(f='<a href="'+j+'" target="_blank">'+f+"</a>"),k='Type: <span class="type">'+f+"</span>");g="";f=="raw"?g=k+" | "+a.toString():i!=""?g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i:h!=""?g=k!=""?h+" | "+k:h:k!=""&&(g=k);g="<p>"+g+"</p>";e=jQuery("<div />",{"class":"expanded"}); jQuery(e).append(g);jQuery("td.title",b).append(e);if(!c)f=jQuery("#refs tr").length,jQuery("td.number",b).text(f),jQuery("#numRefs").text(f);jQuery(b).click(function(){d.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});for(var f=function(){d.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()},l=a.getCitationStrings(),g=jQuery('<span class="all-citations" />'),j=0;j<l.length;j++){i=j+1;for(h="";i>0;)k=--i%26,h=String.fromCharCode(97+ k)+h,i=Math.floor(i/26);i=jQuery('<a href="#">'+h+"</a>");h=function(a){return function(){for(var b=0,c=0,d=proveit.getMWEditValue(),c=0;c<a;c++){b=d.indexOf(l[c],b);if(b==-1)return proveit.log("citationStrings["+c+"]: "+l[c]+" not found. Returning."),!1;b+=l[c].length}b=d.indexOf(l[a],b);b==-1?proveit.log("citationStrings["+a+"]: "+l[a]+" not found."):proveit.highlightLengthAtIndex(b,l[a].length);return!1}}(j);i.click(h);g.append(i)}l.length>1&&(j=jQuery("<p />"),j.append('This reference is cited in the article <span class="num-citations">'+ l.length+" times</span>: ").append(g),e.append(j));a.type!="raw"?(g=jQuery("<button />",{text:"edit"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!1}),g.click(f),jQuery(".edit",b).append(g),g=jQuery("<button />",{"class":"edit",text:"edit this reference"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!0}),g.click(f),e.append(g),jQuery(b).dblclick(f)):jQuery(".edit",b).append("&nbsp;");l.length>0&&(f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"}), jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:!0}),f.click(function(){d.insertRefIntoMWEditBox(a,!1);return!1}),e.append(f));return b},truncateTitle:function(a){var c=a;a.length>86&&(c=c.substring(0,86),a=c.lastIndexOf(" "),a!=-1&&(c=c.substr(0,a),c+=" ..."));return c},formatDate:function(a){var c=a.getFullYear(),b=this.getDescriptions().months[a.getMonth()],a=(a.getDate()<10?"0":"")+a.getDate();return b+" "+a+", "+c},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a, !1))}},window.proveit);proveit.CiteReference.getTypes=function(){return["web","book","journal","conference","encyclopedia","news","newsgroup","press release","interview","episode","video"]};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===void 0;proveit.split._nativeSplit=String.prototype.split;proveit.load(); hyl9kk0iwrtq8jr1ldq9ke7oe57emvn 360734 360733 2011-08-21T21:52:41Z en>Mattflaschen 0 Deploy commit e99b01a23e00 of ProveIt. 360734 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2011, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit e99b01a23e00 as of 2011-08-21 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",descriptions:{en:{agency:"Agency",name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date",accessdate:"Access date", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN",pmid:"PMID", chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL",archivedate:"Date archived", episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID",months:"January,February,March,April,May,June,July,August,September,October,November,December".split(",")}, fi:{agency:"Edustaja",name:"Nimi",author:"Tekij\u00e4",author2:"Tekij\u00e4 kaksi",author3:"Tekij\u00e4 kolme",author4:"Tekij\u00e4 nelj\u00e4",author5:"Tekij\u00e4 viisi",author6:"Tekij\u00e4 kuusi",author7:"Tekij\u00e4 seitsem\u00e4n",author8:"Tekij\u00e4 kahdeksan",author9:"Tekij\u00e4 yhdeks\u00e4n",last:"Sukunimi",last2:"Sukunimi (tekij\u00e4 2)",last3:"Sukunimi (tekij\u00e4 3)",last4:"Sukunimi (tekij\u00e4 4)",last5:"Sukunimi (tekij\u00e4 5)",last6:"Sukunimi (tekij\u00e4 6)",last7:"Sukunimi (tekij\u00e4 7)", last8:"Sukunimi (tekij\u00e4 8)",last9:"Sukunimi (tekij\u00e4 9)",first:"Etunimi",first2:"Etunimi (tekij\u00e4 2)",first3:"Etunimi (tekij\u00e4 3)",first4:"Etunimi (tekij\u00e4 4)",first5:"Etunimi (tekij\u00e4 5)",first6:"Etunimi (tekij\u00e4 6)",first7:"Etunimi (tekij\u00e4 7)",first8:"Etunimi (tekij\u00e4\t8)",first9:"Etunimi (tekij\u00e4 9)",authorlink:"Tekij\u00e4st\u00e4 kertova sivu",title:"Otsikko",publisher:"Julkaisija",year:"Vuosi",location:"Paikka",place:"Ty\u00f6n paikka",isbn:"ISBN",id:"ID", doi:"DOI",page:"Sivu",pages:"Sivuja",quote:"Lainaus",month:"Kuukausi",journal:"Aikakauslehti",edition:"Painos",volume:"Vuosikerta",issue:"Numero",url:"Osoite",date:"Julkaisup\u00e4iv\u00e4",accessdate:"Luettu",coauthors:"Muut tekij\u00e4t",booktitle:"Jatko-osien otsikko",contribution:"Osallistuminen/yhteisty\u00f6",encyclopedia:"Tietosanakirja",newsgroup:"Uutisryhm\u00e4",version:"Versio",site:"Sivusto",newspaper:"Sanomalehti","publication-place":"Julkaisupaikka",editor:"Toimittaja",article:"Artikkeli", pubplace:"Julkaisijan paikka",pubyear:"Julkaisuvuosi",inventor:"Keksij\u00e4","issue-date":"Saatavilla p\u00e4iv\u00e4n\u00e4","patent-number":"Patenttinumero","country-code":"Maakoodi (XX)",work:"Ty\u00f6",format:"Muoto",issn:"ISSN",pmid:"PMID",chapter:"Luku",web:"Verkko",book:"Kirja",conference:"Kokous",news:"Uutiset",paper:"Lehti","press release":"Lehdist\u00f6tiedote",interview:"Haastattelu",subject:"Otsikko",subjectlink:"Artikkelin otsikko",subject2:"Otsikko kaksi",subjectlink2:"Artikkelin kaksi otsikko", subject3:"Otsikko kolme",subjectlink3:"Artikkelin kolme otsikko",subject4:"Otsikko nelj\u00e4",interviewer:"Haastattelija",cointerviewers:"Muut haastattelijat",type:"Tyyppi",program:"Ohjelma",callsign:"Call sign",city:"Kaupunki",archiveurl:"Arkiston osoite",archivedate:"Arkistointip\u00e4iv\u00e4m\u00e4\u00e4r\u00e4",episode:"Jakso",episodelink:"Jakson sivun nimi",series:"Sarja",serieslink:"Sarjan sivun nimi",credits:"Tekij\u00e4t",network:"Verkko",station:"Asema",airdate:"L\u00e4hetysp\u00e4iv\u00e4", began:"Aloitusp\u00e4iv\u00e4",ended:"Lopetusp\u00e4iv\u00e4",season:"Kauden numero",seriesno:"Kauden numero",number:"Numero",minutes:"Minuutit",transcript:"Puhtaaksi kirjoitettu teksti",transcripturl:"Puhtaaksikirjoitetun osoite",video:"Video",people:"Ihmiset",medium:"Tuotantomedia",language:"Kieli",time:"Aika",oclc:"OCLC",ref:"Ankkurin ID-tunnus",months:"tammikuu,helmikuu,maaliskuu,huhtikuu,toukokuu,kes\u00e4kuu,hein\u00e4kuu,elokuu,syyskuu,lokakuu,marraskuu,joulukuu".split(",")}},getDescriptions:function(){return this.descriptions[proveit.LANG]}, log:function(a){typeof console==="object"&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(wgCanonicalNamespace==""||wgPageName=="Wikipedia:Sandbox")&&(wgAction=="edit"||wgAction=="submit")},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do c+=a.offsetLeft,b+=a.offsetTop;while(a=a.offsetParent);return{left:c,top:b}},highlightLengthAtIndex:function(a,c){(a<0||c<0)&&this.log("highlightStringAtIndex: invalid negative arguments");var b= this.getMWEditBox(),d=b.value,e=this.getPosition(b).top;b.value=d.substring(0,a);b.focus();b.scrollTop=1E6;e=b.scrollTop;b.value+=d.substring(a);if(e>0)b.scrollTop=e+this.HALF_EDIT_BOX_HEIGHT;jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});e=this.getPosition(b).top;window.scroll(0,e);return!0},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a);return c==-1?(this.log('Target string "'+a+'" not found.'),!1):this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]}, getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;!a.selectionStart&&document.selection&&(c=c.replace(/\r\n/g,"\n"));return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit",a,!1)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:!1,shouldAddSummary:!0,loadMaximized:!1,includeProveItEditSummary:function(){if(this.shouldAddSummary&& !this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var c=a.getEditSummary();c.value.indexOf("ProveIt")==-1&&(c.value+=" (edited with [[User:ProveIt_GT|ProveIt]])")});this.summaryFunctionAdded=!0}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded=!1;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return!0},clearRefBox:function(){var a= this.getRefBox();if(a==null)return this.log("Ref box is not loaded yet."),!1;a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b)return this.log("insertRefIntoMWEditBox: txtarea is null"),!1;var b=jQuery(b),d=a.getInsertionText(c);b.textSelection("encapsulateSelection",{peri:d,replace:!0});b=b.textSelection("getCaretPosition",{startAndEnd:!0});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a, c){var b=jQuery("div.input-row",c),d=jQuery("#editrefname").val();a.name=d!=""?d:null;a.params={};for(var e,f,d=0;d<b.length;d++)e=b[d],f=jQuery(".paramvalue",e)[0],e=jQuery(e).hasClass("addedrow")?jQuery(".paramdesc",e)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length),this.log("paramName: "+e),f=f.value.trim(),this.log("paramVal: "+f),e!=""&&f!=""&&(a.params[e]=f);if(a.toString()!=a.orig)a.save=!1;a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a, !0),b=jQuery(".selected",this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var d=jQuery("td.number",b).text();jQuery("td.number",c).text(d);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name||"");var c={},b;for(b in a.params)c[b]=a.params[b];var d=a.getDefaultParams();for(b=0;b<d.length;b++)c[d[b]]||(c[d[b]]=""); var d=a.getRequiredParams(),e=[],f;for(f in c)e.push(f);(f=a.getSorter())?e.sort(f):e.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<e.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,this.getDescriptions(),e[b],d[e[b]],!0);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a,jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide(); jQuery("#view-pane").show()};setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,d,e,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);e?(jQuery(i).addClass("required"),jQuery(".delete-field",g).remove()):this.activateRemoveField(g);f?(i.attr("for", this.EDIT_PARAM_PREFIX+d),j.attr("id",this.EDIT_PARAM_PREFIX+d),a=b[d],a||(this.log("Undefined description for param: "+d+". Using directly as description."),a=d),jQuery(i).text(a),jQuery(i).attr("title",d),jQuery(j).val(c[d]),jQuery(g).show()):(jQuery(g).show("highlight",{},"slow"),jQuery(".inputs",a).scrollTop(1E5))},togglestyle:!0,toggleinsert:!1,split:function(a,c,b){if(Object.prototype.toString.call(c)!=="[object RegExp]")return proveit.split._nativeSplit.call(a,c,b);var d=[],e=0,f=(c.ignoreCase? "i":"")+(c.multiline?"m":"")+(c.sticky?"y":""),c=RegExp(c.source,f+"g"),g,i,j;a+="";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(b===void 0||+b<0)b=Infinity;else if(b=Math.floor(+b),!b)return[];for(;i=c.exec(a);){f=i.index+i[0].length;if(f>e&&(d.push(a.slice(e,i.index)),!proveit.split._compliantExecNpcg&&i.length>1&&i[0].replace(g,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===void 0&&(i[a]=void 0)}),i.length>1&&i.index<a.length&&Array.prototype.push.apply(d, i.slice(1)),j=i[0].length,e=f,d.length>=b))break;c.lastIndex===i.index&&c.lastIndex++}e===a.length?(j||!c.test(""))&&d.push(""):d.push(a.slice(e));return d.length>b?d.slice(0,b):d},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs.");this.clearRefBox(); var a=this.getMWEditValue(),c,b={},d=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var e=0;e<a.length;e++){var f=this.makeRef(a[e]);f?(c=f.name)||d.push(f):c=(c=a[e].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);if(c){if(!b[c]&&(b[c]={},!b[c].strings))b[c].strings=[];if(f&&!b[c].reference)b[c].reference=f,d.push(f);b[c].strings.push(a[e])}}for(a=0;a<d.length;a++)d[a].name&&d[a].setCitationStrings(b[d[a].name].strings),this.addNewElement(d[a])}, REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/,makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],d=a.match(this.REF_REGEX);if(d&&d!=null)var e=d[1]||d[2]||d[3]; d=b.split(/\|/g);if(c==this.CiteReference)var f=d[0].toLowerCase().indexOf("e"),g=d[0].indexOf("}"),f=d[0].substring(f+1,g!=-1?g:d[0].length).trim()}a=new c({name:e,type:f,save:!0,inMWEditBox:!0,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(e=0;e<b.length;e++)d=b[e].trim().replace(/(?:\s*\|)*(.*)/,"$1"),f=c[e].trim(),f!=""&&(a.params[d]=f)}return a},AbstractReference:function(a){if(!this.setType)this.setType=function(a){this.type=a};this.update=function(){var a= this.toString(),b=this.getCitationStrings();if(b.length>0)for(var d=0;d<b.length;d++)b[d]==this.orig&&(proveit.log("Updating "+b[d]+" to "+a),b[d]=a);else this.name!=null&&(proveit.log("Adding "+a+" to citationStrings"),b.push(a))};this.name=a.name!=""?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};this.getSorter=function(){var a=this;return function(b,d){var e=a.getSortIndex(b),f=a.getSortIndex(d);return e!=-1&&f!=-1?e-f:b<d?-1:b== d?0:1}};this.isValid=function(){return!0};this.getLabel=function(){var a="";if(this.params.author)a=this.params.author+"; ";else if(this.params.last)a=this.params.last,this.params.first&&(a+=", "+this.params.first),a+="; ";this.params.title&&(a+=this.params.title);if(a==""){for(var b in this.params)break;b&&(a=b)}return a};this.getInsertionText=function(a){proveit.log("getInsertionText");if(a)return this.toString();else if(this.name)return'<ref name="'+this.name+'" />';else throw Error("getInsertionText: ref.name is null"); };this.updateInText=function(){var a=proveit.getMWEditBox();if(a&&a!=null){a.focus();var b=proveit.getMWEditValue(),b=b.replace(this.orig,this.toString());a.value=b;this.orig=this.toString();this.save=!0;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(a,b){var d=this.name?'<ref name="'+this.name+'">':"<ref>";d+="{{"+a+(b?" "+this.type:"");for(var e in this.params)d+=" | "+e+"="+this.params[e];d+="}}</ref>";return d};this.citationStrings=[];this.setCitationStrings=function(a){this.citationStrings= a};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+"page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news",newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(a){var b=c[a];this.type=b!=null?b:a};proveit.AbstractReference.call(this, a);this.getSortIndex=function(a){return jQuery.inArray(a,"url,title,encyclopedia,publisher,work,date,agency,accessdate,author,last,first,subject,subjectlink,inventor,editor,author2,last2,first2,subject2,subjectlink2,author3,last3,first3,subject3,subjectlink3,author4,last4,first4,subject4,author5,last5,first5,author6,last6,first6,author7,last7,first7,author8,last8,first8,author9,last9,first9,authorlink,coauthors,interviewer,cointerviewers,type,newsgroup,journal,booktitle,program,episodelink,series,serieslink,credits,network,station,callsign,city,airdate,began,ended,season,seriesno,number,minutes,transcript,transcripturl,people,year,month,article,contribution,format,medium,newspaper,conference,volume,edition,issue,location,pages,page,language,isbn,issn,oclc,doi,pmid,id,archiveurl,archivedate,time,quote,ref".split(","))}; this.toString=function(){return this.toStringInternal("cite",!0)};var b={web:{url:!0,title:!0},book:{title:!0},journal:{title:!0},conference:{title:!0},encyclopedia:{title:!0,encyclopedia:!0},news:{title:!0,work:!0,date:!0},newsgroup:{title:!0},"press release":{title:!0},interview:{last:!0},episode:{title:!0},video:{title:!0}};this.getRequiredParams=function(){var a=b[this.type];return a?a:{}};var d={web:"url,title,author,accessdate,work,publisher,date,pages".split(","),book:"title,author,authorlink,year,isbn,publisher,location,pages".split(","), journal:"title,author,journal,volume,issue,year,month,pages,url,doi".split(","),conference:"conference,title,booktitle,author,editor,year,month,url,id,accessdate,location,pages,publisher".split(","),encyclopedia:"title,encyclopedia,author,editor,accessdate,edition,year,publisher,volume,location,pages".split(","),news:"title,author,url,work,date,accessdate,pages,location,agency".split(","),newsgroup:"title,author,date,newsgroup,id,url,accessdate".split(","),"press release":["title","url","publisher", "date","accessdate"],interview:"last,first,subjectlink,interviewer,title,callsign,city,date,program,accessdate".split(","),episode:"title,series,credits,airdate,city,network,season".split(","),video:"people,date,url,title,medium,location,publisher".split(",")};this.getDefaultParams=function(){var a=d[this.type];return a?a:[]};this.isValid=function(){if(this.type=="")return!1;var a=this.getRequiredParams(),b=!0,c;for(c in a)if(a[c]&&(b&=c in this.params,!b))break;return b};var e={web:"page_white_world.png", book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png",episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var a=e[this.type];return a?proveit.STATIC_BASE+a:f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url","author","title","date","accessdate"],news:"author,title,newspaper,url,publication-place,volume,issue,date,pages".split(","), encyclopedia:"author,editor,contribution,title,publisher,place,year,volume,pages".split(","),book:["author","title","publisher","place","year"],journal:"author,title,journal,volume,issue,year,pages".split(","),patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(a){return"last,first,url,author,editor,contribution,author-link,last2,first2,author2-link,publication-date,inventor,title,issue-date,patent-number,country-code,journal,volume,newspaper,issue,date,publisher,place,year,edition,publication-place,series,version,pages,page,id,isbn,doi,oclc,accessdate".split(",").indexOf(a)}; this.toString=function(){return this.toStringInternal("Citation",!1)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]:["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+"raw.png"}},getRefFromAddPane:function(a){for(var c=a.id,c=new (this.togglestyle? this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c}),b,a=jQuery(".paramlist",a)[0],d=jQuery("div",a),e=0;e<d.length;e++){b=d[e];this.log("getRefFromAddPane: i: "+e+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0],a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName); this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);a!=""&&b!=""&&(c.params[a]=b)}c.update();this.log("Exiting getRefFromAddPane");return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,!0);a.save=!0;a.inMWEditBox=!0},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)},activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight", {},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0);this.clearCitePanes(c);var b=a.value,d=document.getElementById("dummyCitePane").cloneNode(!0);d.id=b.replace(" ","_");jQuery(".ref-name-row",d).children("input").attr("id","addrefname");jQuery(".ref-name-row",d).children("label").attr("for","addrefname");a=a.id=="citemenu"?new this.CiteReference({}):new this.CitationReference({}); a.type=b;var b=this.getDescriptions(),e=a.getDefaultParams().slice(0);e.sort(a.getSorter());for(var f=0;f<e.length;f++)a.params[e[f]]="";this.log("changeAddPane: newRef: "+a);e=[];for(j in a.params)e.push(j);e.sort(a.getSorter());for(var g=a.getRequiredParams(),i=jQuery(".paramlist",d)[0],f=0;f<e.length;f++){var j=e[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(!0);var k=jQuery(".paramdesc",h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h); k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);j=="accessdate"&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else h=document.getElementById("addedparamrow").cloneNode(!0),jQuery(".paramdesc",h)[0].setAttribute("value",j);h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(d).show();c.insertBefore(d,c.firstChild);this.log("Exiting changeAddPane")}, createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css");var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),d=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),e=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png",alt:"ProveIt",height:30,width:118});d.append(e);b.append(d);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b); e=jQuery("<ul/>");d=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References (");var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");d.append(b);e.append(d);g=jQuery("<li/>");d=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(d);e.append(g);c.append(e);var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}}),e=jQuery("<div/>",{id:"view-pane"}),g=jQuery("<div/>",{"class":"scroll", style:"height: 210px;"}),j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>",{"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);e.append(g);i.append(e);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});e=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll", style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.","class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>",{"class":"paramlist"});e.append(h);e.append(g);k.append(e);var l=jQuery("<div/>",{id:"edit-buttons"}),e=jQuery("<button/>", {style:"margin-right: 50px;"}).append("add field");l.append(e);e=jQuery("<span/>",{"class":"required",text:"bold"});l.append(e).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"});l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane","class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"})); c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k);l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row",style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone()); c.append(h);var p=jQuery("<div/>",{id:"add-tab",css:{display:"none"}}),h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"}),n=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}),m=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});n.append(m);for(var q=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(q.get(0))}}),o=this.CiteReference.getTypes(),k=this.getDescriptions(),l=0;l<o.length;l++)q.append(jQuery("<option/>", {value:o[l],text:k[o[l]]}));n.append(q);h.append(n);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));n=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"});m=m.clone().attr("for","citationmenu");n.append(m);for(var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}}),m="web,book,journal,encyclopedia,news,patent".split(","),o=0;o<m.length;o++)r.append(jQuery("<option/>",{value:m[l],text:k[m[l]]}));n.append(r);h.append(n).append(jQuery("<div/>", {"class":"addpanes",id:"citationpanes",style:"display: none;"}));p.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(e.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone());p.append(h);c.append(p);a.append(c);jQuery(document.body).prepend(a);var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(a,b){switch(b.index){case 1:s(), proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(d).click(function(){jQuery(p).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check",secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0))); jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:!1});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:!1});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var d=this,e="",f="";if(a.params.title!=null)e=a.params.title,f=this.truncateTitle(e);jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",e);e="";a.params.year?e=a.params.year:a.params.date&&(f=a.params.date.match(/^([12]\d{3})/))&&(e=f[1]);var g="";a.params.author? g=a.params.author:a.params.last&&(g=a.params.last);if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="",f=a.type;switch(f){case "web":j=a.params.url;break;case "book":a.params.isbn!=null&&(j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn);break;case "journal":case "conference":a.params.doi!=null&&(j="http://dx.doi.org/"+a.params.doi);break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";g!=""&&(i='By: <span class="author">'+g+"</span>");e!=""&&(h='Date: <span class="date">'+e+"</span>");f!=null&&(j!=""&&(f='<a href="'+j+'" target="_blank">'+f+"</a>"),k='Type: <span class="type">'+f+"</span>");g="";f=="raw"?g=k+" | "+a.toString():i!=""?g=h!=""?k!=""?i+" | "+h+" | "+k:i+" | "+h:k!=""?i+" | "+k:i:h!=""?g=k!=""?h+" | "+k:h:k!=""&&(g=k);g="<p>"+g+"</p>";e=jQuery("<div />",{"class":"expanded"}); jQuery(e).append(g);jQuery("td.title",b).append(e);if(!c)f=jQuery("#refs tr").length,jQuery("td.number",b).text(f),jQuery("#numRefs").text(f);jQuery(b).click(function(){d.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});for(var f=function(){d.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()},l=a.getCitationStrings(),g=jQuery('<span class="all-citations" />'),j=0;j<l.length;j++){i=j+1;for(h="";i>0;)k=--i%26,h=String.fromCharCode(97+ k)+h,i=Math.floor(i/26);i=jQuery('<a href="#">'+h+"</a>");h=function(a){return function(){for(var b=0,c=0,d=proveit.getMWEditValue(),c=0;c<a;c++){b=d.indexOf(l[c],b);if(b==-1)return proveit.log("citationStrings["+c+"]: "+l[c]+" not found. Returning."),!1;b+=l[c].length}b=d.indexOf(l[a],b);b==-1?proveit.log("citationStrings["+a+"]: "+l[a]+" not found."):proveit.highlightLengthAtIndex(b,l[a].length);return!1}}(j);i.click(h);g.append(i)}l.length>1&&(j=jQuery("<p />"),j.append('This reference is cited in the article <span class="num-citations">'+ l.length+" times</span>: ").append(g),e.append(j));a.type!="raw"?(g=jQuery("<button />",{text:"edit"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!1}),g.click(f),jQuery(".edit",b).append(g),g=jQuery("<button />",{"class":"edit",text:"edit this reference"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!0}),g.click(f),e.append(g),jQuery(b).dblclick(f)):jQuery(".edit",b).append("&nbsp;");l.length>0&&(f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"}), jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:!0}),f.click(function(){d.insertRefIntoMWEditBox(a,!1);return!1}),e.append(f));return b},truncateTitle:function(a){var c=a;a.length>86&&(c=c.substring(0,86),a=c.lastIndexOf(" "),a!=-1&&(c=c.substr(0,a),c+=" ..."));return c},formatDate:function(a){var c=a.getFullYear(),b=this.getDescriptions().months[a.getMonth()],a=(a.getDate()<10?"0":"")+a.getDate();return b+" "+a+", "+c},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a, !1))}},window.proveit);proveit.CiteReference.getTypes=function(){return"web,book,journal,conference,encyclopedia,news,newsgroup,press release,interview,episode,video".split(",")};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};proveit.split._compliantExecNpcg=/()??/.exec("")[1]===void 0;proveit.split._nativeSplit=String.prototype.split;proveit.load(); s152plf4pbmgi9mxlt1jhihonlm8iwu 360735 360734 2012-03-01T04:04:43Z en>Mattflaschen 0 Deploy commit dce6753d7d50 of ProveIt. 360735 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2011, Georgia Tech * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit dce6753d7d50 as of 2012-03-01 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ window.proveit=jQuery.extend({HALF_EDIT_BOX_HEIGHT:200,LANG:"en",NEW_PARAM_PREFIX:"newparam",EDIT_PARAM_PREFIX:"editparam",STATIC_BASE:"http://proveit-js.googlecode.com/hg/static/",JQUERYUI_SCRIPT_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js",JQUERYUI_STYLES_URL:"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css",descriptions:{en:{agency:"Agency",name:"Name",author:"Author (L, F)",author2:"Author two (L, F)",author3:"Author three (L, F)",author4:"Author four (L, F)", author5:"Author five (L, F)",author6:"Author six (L, F)",author7:"Author seven (L, F)",author8:"Author eight (L, F)",author9:"Author nine (L, F)",last:"Last name",last2:"Last name (auth. two)",last3:"Last name (auth. three)",last4:"Last name (auth. four)",last5:"Last name (auth. five)",last6:"Last name (auth. six)",last7:"Last name (auth. seven)",last8:"Last name (auth. eight)",last9:"Last name (auth. nine)",first:"First name",first2:"First name (auth. two)",first3:"First name (auth. three)",first4:"First name (auth. four)", first5:"First name (auth. five)",first6:"First name (auth. six)",first7:"First name (auth. seven)",first8:"First name (auth. eight)",first9:"First name (auth. nine)",authorlink:"Author article name",title:"Title",publisher:"Publisher",year:"Year",location:"Location",place:"Location of work",isbn:"ISBN",id:"ID",doi:"DOI",page:"Page",pages:"Pages",quote:"Quote",month:"Month",journal:"Journal",edition:"Edition",volume:"Volume",issue:"Issue",url:"URL",date:"Publication date",accessdate:"Access date", coauthors:"Co-authors",booktitle:"Title of Proceedings",contribution:"Contribution/Chapter",encyclopedia:"Encyclopedia",newsgroup:"Newsgroup",version:"Version",site:"Site",newspaper:"Newspaper","publication-place":"Publication location",editor:"Editor (L, F)",article:"Article",pubplace:"Publisher location",pubyear:"Publication year",inventor:"Inventor (L, F)","issue-date":"Issue date","patent-number":"Patent number","country-code":"Country code (XX)",work:"Work",format:"Format",issn:"ISSN",pmid:"PMID", chapter:"Chapter",web:"Web",book:"Book",conference:"Conference",news:"News",paper:"Paper","press release":"Press release",interview:"Interview",subject:"Subject",subjectlink:"Subject article name",subject2:"Subject two",subjectlink2:"Subject two article name",subject3:"Subject three",subjectlink3:"Subject three article name",subject4:"Subject four",interviewer:"Interviewer",cointerviewers:"Co-interviewers",type:"Type",program:"Program",callsign:"Call sign",city:"City",archiveurl:"Archive URL",archivedate:"Date archived", episode:"Episode",episodelink:"Episode article name",series:"Series",serieslink:"Series article name",credits:"Credits",network:"Network",station:"Station",airdate:"Airdate",began:"Start date",ended:"End date",season:"Season number",seriesno:"Season number",number:"Number",minutes:"Minutes",transcript:"Transcript",transcripturl:"Transcript URL",video:"Video",people:"People",medium:"Production medium",language:"Language",time:"Time",oclc:"OCLC",ref:"Anchor ID",months:"January,February,March,April,May,June,July,August,September,October,November,December".split(",")}, fi:{agency:"Edustaja",name:"Nimi",author:"Tekij\u00e4",author2:"Tekij\u00e4 kaksi",author3:"Tekij\u00e4 kolme",author4:"Tekij\u00e4 nelj\u00e4",author5:"Tekij\u00e4 viisi",author6:"Tekij\u00e4 kuusi",author7:"Tekij\u00e4 seitsem\u00e4n",author8:"Tekij\u00e4 kahdeksan",author9:"Tekij\u00e4 yhdeks\u00e4n",last:"Sukunimi",last2:"Sukunimi (tekij\u00e4 2)",last3:"Sukunimi (tekij\u00e4 3)",last4:"Sukunimi (tekij\u00e4 4)",last5:"Sukunimi (tekij\u00e4 5)",last6:"Sukunimi (tekij\u00e4 6)",last7:"Sukunimi (tekij\u00e4 7)", last8:"Sukunimi (tekij\u00e4 8)",last9:"Sukunimi (tekij\u00e4 9)",first:"Etunimi",first2:"Etunimi (tekij\u00e4 2)",first3:"Etunimi (tekij\u00e4 3)",first4:"Etunimi (tekij\u00e4 4)",first5:"Etunimi (tekij\u00e4 5)",first6:"Etunimi (tekij\u00e4 6)",first7:"Etunimi (tekij\u00e4 7)",first8:"Etunimi (tekij\u00e4\t8)",first9:"Etunimi (tekij\u00e4 9)",authorlink:"Tekij\u00e4st\u00e4 kertova sivu",title:"Otsikko",publisher:"Julkaisija",year:"Vuosi",location:"Paikka",place:"Ty\u00f6n paikka",isbn:"ISBN",id:"ID", doi:"DOI",page:"Sivu",pages:"Sivuja",quote:"Lainaus",month:"Kuukausi",journal:"Aikakauslehti",edition:"Painos",volume:"Vuosikerta",issue:"Numero",url:"Osoite",date:"Julkaisup\u00e4iv\u00e4",accessdate:"Luettu",coauthors:"Muut tekij\u00e4t",booktitle:"Jatko-osien otsikko",contribution:"Osallistuminen/yhteisty\u00f6",encyclopedia:"Tietosanakirja",newsgroup:"Uutisryhm\u00e4",version:"Versio",site:"Sivusto",newspaper:"Sanomalehti","publication-place":"Julkaisupaikka",editor:"Toimittaja",article:"Artikkeli", pubplace:"Julkaisijan paikka",pubyear:"Julkaisuvuosi",inventor:"Keksij\u00e4","issue-date":"Saatavilla p\u00e4iv\u00e4n\u00e4","patent-number":"Patenttinumero","country-code":"Maakoodi (XX)",work:"Ty\u00f6",format:"Muoto",issn:"ISSN",pmid:"PMID",chapter:"Luku",web:"Verkko",book:"Kirja",conference:"Kokous",news:"Uutiset",paper:"Lehti","press release":"Lehdist\u00f6tiedote",interview:"Haastattelu",subject:"Otsikko",subjectlink:"Artikkelin otsikko",subject2:"Otsikko kaksi",subjectlink2:"Artikkelin kaksi otsikko", subject3:"Otsikko kolme",subjectlink3:"Artikkelin kolme otsikko",subject4:"Otsikko nelj\u00e4",interviewer:"Haastattelija",cointerviewers:"Muut haastattelijat",type:"Tyyppi",program:"Ohjelma",callsign:"Call sign",city:"Kaupunki",archiveurl:"Arkiston osoite",archivedate:"Arkistointip\u00e4iv\u00e4m\u00e4\u00e4r\u00e4",episode:"Jakso",episodelink:"Jakson sivun nimi",series:"Sarja",serieslink:"Sarjan sivun nimi",credits:"Tekij\u00e4t",network:"Verkko",station:"Asema",airdate:"L\u00e4hetysp\u00e4iv\u00e4", began:"Aloitusp\u00e4iv\u00e4",ended:"Lopetusp\u00e4iv\u00e4",season:"Kauden numero",seriesno:"Kauden numero",number:"Numero",minutes:"Minuutit",transcript:"Puhtaaksi kirjoitettu teksti",transcripturl:"Puhtaaksikirjoitetun osoite",video:"Video",people:"Ihmiset",medium:"Tuotantomedia",language:"Kieli",time:"Aika",oclc:"OCLC",ref:"Ankkurin ID-tunnus",months:"tammikuu,helmikuu,maaliskuu,huhtikuu,toukokuu,kes\u00e4kuu,hein\u00e4kuu,elokuu,syyskuu,lokakuu,marraskuu,joulukuu".split(",")}},getDescriptions:function(){return this.descriptions[proveit.LANG]}, log:function(a){"object"===typeof console&&console.log&&console.log("[ProveIt] %o",a)},isSupportedEditPage:function(){return(""==wgCanonicalNamespace||"User"==wgCanonicalNamespace||"Wikipedia:Sandbox"==wgPageName)&&("edit"==wgAction||"submit"==wgAction)},getRefBox:function(){return jQuery("#refs")},getPosition:function(a){var c=0,b=0;do c+=a.offsetLeft,b+=a.offsetTop;while(a=a.offsetParent);return{left:c,top:b}},highlightLengthAtIndex:function(a,c){(0>a||0>c)&&this.log("highlightStringAtIndex: invalid negative arguments"); var b=this.getMWEditBox(),d=b.value,e=this.getPosition(b).top;b.value=d.substring(0,a);b.focus();b.scrollTop=1E6;e=b.scrollTop;b.value+=d.substring(a);0<e&&(b.scrollTop=e+this.HALF_EDIT_BOX_HEIGHT);jQuery(b).focus().textSelection("setSelection",{start:a,end:a+c});e=this.getPosition(b).top;window.scroll(0,e);return!0},highlightTargetString:function(a){var c=this.getMWEditValue().indexOf(a);return-1==c?(this.log('Target string "'+a+'" not found.'),!1):this.highlightLengthAtIndex(c,a.length)},getMWEditBox:function(){return jQuery("#wpTextbox1")[0]}, getMWEditValue:function(){var a=this.getMWEditBox(),c=a.value;!a.selectionStart&&document.selection&&(c=c.replace(/\r\n/g,"\n"));return c},getMWEditForm:function(){return jQuery("#editform")[0]},addOnsubmit:function(a){var c=this.getMWEditForm();if(!c)throw Error("No edit form, possibly due to protected page.");c.addEventListener("submit",a,!1)},getEditSummary:function(){return jQuery("#wpSummary")[0]},summaryFunctionAdded:!1,shouldAddSummary:!0,loadMaximized:!1,includeProveItEditSummary:function(){if(this.shouldAddSummary&& !this.summaryFunctionAdded)try{var a=this;this.addOnsubmit(function(){var c=a.getEditSummary();-1==c.value.indexOf("ProveIt")&&(c.value+=" (edited with [[User:ProveIt_GT|ProveIt]])")});this.summaryFunctionAdded=!0}catch(c){this.log("Failed to add onsubmit handler. e.message: "+c.message)}},load:function(){this.summaryFunctionAdded=!1;this.isSupportedEditPage()&&jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL,function(){addOnloadHook(function(){proveit.createGUI()})});return!0},clearRefBox:function(){var a= this.getRefBox();if(null==a)return this.log("Ref box is not loaded yet."),!1;a=jQuery("tr:not('tr#dummyRef')",a);jQuery(a).remove()},insertRefIntoMWEditBox:function(a,c){var b=this.getMWEditBox();if(!b)return this.log("insertRefIntoMWEditBox: txtarea is null"),!1;var b=jQuery(b),d=a.getInsertionText(c);b.textSelection("encapsulateSelection",{peri:d,replace:!0});b=b.textSelection("getCaretPosition",{startAndEnd:!0});this.highlightLengthAtIndex(b[0],b[1]-b[0]);this.includeProveItEditSummary()},changeRefFromEditPane:function(a, c){var b=jQuery("div.input-row",c),d=jQuery("#editrefname").val();a.name=""!=d?d:null;a.params={};for(var e,f,d=0;d<b.length;d++)e=b[d],f=jQuery(".paramvalue",e)[0],e=jQuery(e).hasClass("addedrow")?jQuery(".paramdesc",e)[0].value.trim():f.id.substring(this.EDIT_PARAM_PREFIX.length),this.log("paramName: "+e),f=f.value.trim(),this.log("paramVal: "+f),""!=e&&""!=f&&(a.params[e]=f);a.toString()!=a.orig&&(a.save=!1);a.update();return a},saveRefFromEdit:function(a){if(!a.save){var c=this.makeRefBoxRow(a, !0),b=jQuery(".selected",this.getRefBox()).get(0);this.log("newRichItem: "+c+", oldRichItem: "+b+"oldRichItem.parentNode: "+b.parentNode);var d=jQuery("td.number",b).text();jQuery("td.number",c).text(d);b.parentNode.replaceChild(c,b);jQuery(c).addClass("selected");a.updateInText();this.includeProveItEditSummary()}},updateEditPane:function(a){jQuery("#editrefname").val(a.name||"");var c={},b;for(b in a.params)c[b]=a.params[b];var d=a.getDefaultParams();for(b=0;b<d.length;b++)c[d[b]]||(c[d[b]]=""); var d=a.getRequiredParams(),e=[],f;for(f in c)e.push(f);(f=a.getSorter())?e.sort(f):e.sort();jQuery("#edit-fields").children(".paramlist").children().remove("div:not(.hidden)");for(b=0;b<e.length;b++)this.addPaneRow(jQuery("#edit-pane").get(),c,this.getDescriptions(),e[b],d[e[b]],!0);var g=jQuery("#edit-buttons .accept"),i=function(){proveit.log("Entering acceptEdit");proveit.changeRefFromEditPane(a,jQuery("#edit-pane").get());proveit.saveRefFromEdit(a);g.unbind("click",i);jQuery("#edit-pane").hide(); jQuery("#view-pane").show()};setTimeout(function(){jQuery("#edit-fields").scrollTop(0)},0);g.click(i);jQuery(".tab-link").one("click",function(){g.unbind("click",i)})},addPaneRow:function(a,c,b,d,e,f){var g=jQuery("#"+(f?"preloadedparamrow":"addedparamrow")).clone();jQuery(g).attr("id","");var i=jQuery(".paramdesc",g).eq(0),j=jQuery(".paramvalue",g).eq(0);jQuery(".paramlist",a).append(g);e?(jQuery(i).addClass("required"),jQuery(".delete-field",g).remove()):this.activateRemoveField(g);f?(i.attr("for", this.EDIT_PARAM_PREFIX+d),j.attr("id",this.EDIT_PARAM_PREFIX+d),a=b[d],a||(this.log("Undefined description for param: "+d+". Using directly as description."),a=d),jQuery(i).text(a),jQuery(i).attr("title",d),jQuery(j).val(c[d]),jQuery(g).show()):(jQuery(g).show("highlight",{},"slow"),jQuery(".inputs",a).scrollTop(1E5))},togglestyle:!0,toggleinsert:!1,split:function(a,c,b){if("[object RegExp]"!==Object.prototype.toString.call(c))return proveit.split._nativeSplit.call(a,c,b);var d=[],e=0,f=(c.ignoreCase? "i":"")+(c.multiline?"m":"")+(c.sticky?"y":""),c=RegExp(c.source,f+"g"),g,i,j,a=a+"";proveit.split._compliantExecNpcg||(g=RegExp("^"+c.source+"$(?!\\s)",f));if(void 0===b||0>+b)b=Infinity;else if(b=Math.floor(+b),!b)return[];for(;i=c.exec(a);){f=i.index+i[0].length;if(f>e&&(d.push(a.slice(e,i.index)),!proveit.split._compliantExecNpcg&&1<i.length&&i[0].replace(g,function(){for(var a=1;a<arguments.length-2;a++)void 0===arguments[a]&&(i[a]=void 0)}),1<i.length&&i.index<a.length&&Array.prototype.push.apply(d, i.slice(1)),j=i[0].length,e=f,d.length>=b))break;c.lastIndex===i.index&&c.lastIndex++}e===a.length?(j||!c.test(""))&&d.push(""):d.push(a.slice(e));return d.length>b?d.slice(0,b):d},splitNameVals:function(a){var c={};c.names=proveit.split(a.substring(a.indexOf("|")+1),/=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/);c.names.length--;c.values=proveit.split(a.substring(a.indexOf("=")+1,a.indexOf("}}")),/\|[^|=]*=/);return c},scanForRefs:function(){this.log("Entering scanForRefs.");this.clearRefBox(); var a=this.getMWEditValue(),c,b={},d=[];a.match(/<[\s]*ref[^\/>]*>/gi);if(a=a.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi))for(var e=0;e<a.length;e++){var f=this.makeRef(a[e]);f?(c=f.name)||d.push(f):c=(c=a[e].match(this.REF_REGEX))&&(c[1]||c[2]||c[3]);c&&(b[c]||(b[c]={},b[c].strings||(b[c].strings=[])),f&&!b[c].reference&&(b[c].reference=f,d.push(f)),b[c].strings.push(a[e]))}for(a=0;a<d.length;a++)d[a].name&&d[a].setCitationStrings(b[d[a].name].strings),this.addNewElement(d[a])},REF_REGEX:/<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, makeRef:function(a){var c=/<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(a);this.log("refText: "+a+"; isReference: "+c);if(!c)return null;c=a.match(/{{[\s]*cite/i)?this.CiteReference:a.match(/{{[\s]*Citation/i)?this.CitationReference:this.RawReference;if(c!=this.RawReference){var b=a.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0],d=a.match(this.REF_REGEX);if(d&&null!=d)var e=d[1]||d[2]||d[3];d=b.split(/\|/g);if(c==this.CiteReference)var f=d[0].toLowerCase().indexOf("e"),g=d[0].indexOf("}"), f=d[0].substring(f+1,-1!=g?g:d[0].length).trim()}a=new c({name:e,type:f,save:!0,inMWEditBox:!0,orig:a});if(c!=this.RawReference){c=this.splitNameVals(b);b=c.names;c=c.values;for(e=0;e<b.length;e++)d=b[e].trim().replace(/(?:\s*\|)*(.*)/,"$1"),f=c[e].trim(),""!=f&&(a.params[d]=f)}return a},AbstractReference:function(a){this.setType||(this.setType=function(a){this.type=a});this.update=function(){var a=this.toString(),b=this.getCitationStrings();if(0<b.length)for(var d=0;d<b.length;d++)b[d]==this.orig&& (proveit.log("Updating "+b[d]+" to "+a),b[d]=a);else null!=this.name&&(proveit.log("Adding "+a+" to citationStrings"),b.push(a))};this.name=""!=a.name?a.name:null;this.setType(a.type);this.save=a.save;this.inMWEditBox=a.inMWEditBox;this.orig=a.orig;this.params={};this.getSorter=function(){var a=this;return function(b,d){var e=a.getSortIndex(b),f=a.getSortIndex(d);return-1!=e&&-1!=f?e-f:b<d?-1:b==d?0:1}};this.isValid=function(){return!0};this.getLabel=function(){var a="";this.params.author?a=this.params.author+ "; ":this.params.last&&(a=this.params.last,this.params.first&&(a+=", "+this.params.first),a+="; ");this.params.title&&(a+=this.params.title);if(""==a){for(var b in this.params)break;b&&(a=b)}return a};this.getInsertionText=function(a){proveit.log("getInsertionText");if(a)return this.toString();if(this.name)return'<ref name="'+this.name+'" />';throw Error("getInsertionText: ref.name is null");};this.updateInText=function(){var a=proveit.getMWEditBox();if(a&&null!=a){a.focus();var b=proveit.getMWEditValue(), b=b.replace(this.orig,this.toString());a.value=b;this.orig=this.toString();this.save=!0;proveit.highlightTargetString(this.toString())}};this.toStringInternal=function(a,b){var d=this.name?'<ref name="'+this.name+'">':"<ref>",d=d+("{{"+a+(b?" "+this.type:"")),e;for(e in this.params)d+=" | "+e+"="+this.params[e];return d+"}}</ref>"};this.citationStrings=[];this.setCitationStrings=function(a){this.citationStrings=a};this.getCitationStrings=function(){return this.citationStrings};this.getIcon=function(){return proveit.STATIC_BASE+ "page_white.png"}},CiteReference:function(a){var c={web:"web",book:"book",journal:"journal",conference:"conference",encyclopedia:"encyclopedia",news:"news",newsgroup:"newsgroup",paper:"journal","press release":"press release",pressrelease:"press release",interview:"interview",episode:"episode",video:"video"};this.setType=function(a){var b=c[a];this.type=null!=b?b:a};proveit.AbstractReference.call(this,a);this.getSortIndex=function(a){return jQuery.inArray(a,"url,title,encyclopedia,publisher,work,date,agency,accessdate,author,last,first,subject,subjectlink,inventor,editor,author2,last2,first2,subject2,subjectlink2,author3,last3,first3,subject3,subjectlink3,author4,last4,first4,subject4,author5,last5,first5,author6,last6,first6,author7,last7,first7,author8,last8,first8,author9,last9,first9,authorlink,coauthors,interviewer,cointerviewers,type,newsgroup,journal,booktitle,program,episodelink,series,serieslink,credits,network,station,callsign,city,airdate,began,ended,season,seriesno,number,minutes,transcript,transcripturl,people,year,month,article,contribution,format,medium,newspaper,conference,volume,edition,issue,location,pages,page,language,isbn,issn,oclc,doi,pmid,id,archiveurl,archivedate,time,quote,ref".split(","))}; this.toString=function(){return this.toStringInternal("cite",!0)};var b={web:{url:!0,title:!0},book:{title:!0},journal:{title:!0},conference:{title:!0},encyclopedia:{title:!0,encyclopedia:!0},news:{title:!0,work:!0,date:!0},newsgroup:{title:!0},"press release":{title:!0},interview:{last:!0},episode:{title:!0},video:{title:!0}};this.getRequiredParams=function(){var a=b[this.type];return a?a:{}};var d={web:"url,title,author,accessdate,work,publisher,date,pages".split(","),book:"title,author,authorlink,year,isbn,publisher,location,pages".split(","), journal:"title,author,journal,volume,issue,year,month,pages,url,doi".split(","),conference:"conference,title,booktitle,author,editor,year,month,url,id,accessdate,location,pages,publisher".split(","),encyclopedia:"title,encyclopedia,author,editor,accessdate,edition,year,publisher,volume,location,pages".split(","),news:"title,author,url,work,date,accessdate,pages,location,agency".split(","),newsgroup:"title,author,date,newsgroup,id,url,accessdate".split(","),"press release":["title","url","publisher", "date","accessdate"],interview:"last,first,subjectlink,interviewer,title,callsign,city,date,program,accessdate".split(","),episode:"title,series,credits,airdate,city,network,season".split(","),video:"people,date,url,title,medium,location,publisher".split(",")};this.getDefaultParams=function(){var a=d[this.type];return a?a:[]};this.isValid=function(){if(""==this.type)return!1;var a=this.getRequiredParams(),b=!0,c;for(c in a)if(a[c]&&(b&=c in this.params,!b))break;return b};var e={web:"page_white_world.png", book:"book.png",journal:"page_white_text.png",news:"newspaper.png",newsgroup:"comments.png","press release":"transmit_blue.png",interview:"telephone.png",episode:"television.png",video:"film.png"},f=this.getIcon;this.getIcon=function(){var a=e[this.type];return a?proveit.STATIC_BASE+a:f.call(this)}},CitationReference:function(a){proveit.AbstractReference.call(this,a);var c={},b={web:["url","author","title","date","accessdate"],news:"author,title,newspaper,url,publication-place,volume,issue,date,pages".split(","), encyclopedia:"author,editor,contribution,title,publisher,place,year,volume,pages".split(","),book:["author","title","publisher","place","year"],journal:"author,title,journal,volume,issue,year,pages".split(","),patent:["inventor","title","issue-date","patent-number","country-code"]};this.getSortIndex=function(a){return"last,first,url,author,editor,contribution,author-link,last2,first2,author2-link,publication-date,inventor,title,issue-date,patent-number,country-code,journal,volume,newspaper,issue,date,publisher,place,year,edition,publication-place,series,version,pages,page,id,isbn,doi,oclc,accessdate".split(",").indexOf(a)}; this.toString=function(){return this.toStringInternal("Citation",!1)};this.getRequiredParams=function(){return c};this.getDefaultParams=function(){return this.type?b[this.type]:["url","title","author","date","publisher"]}},RawReference:function(a){proveit.AbstractReference.call(this,a);this.type="raw";this.toString=function(){return this.orig};this.params.title=this.orig;this.getIcon=function(){return proveit.STATIC_BASE+"raw.png"}},getRefFromAddPane:function(a){for(var c=a.id,c=new (this.togglestyle? this.CiteReference:this.CitationReference)({name:jQuery("#addrefname").val(),type:c}),b,a=jQuery(".paramlist",a)[0],d=jQuery("div",a),e=0;e<d.length;e++){b=d[e];this.log("getRefFromAddPane: i: "+e+", paramRow: "+b);var f=jQuery(".paramvalue",b)[0],a=jQuery(b).hasClass("addedrow")?jQuery(".paramdesc",b)[0].value.trim():f.id.substring(this.NEW_PARAM_PREFIX.length);this.log("getRefFromAddPane: paramRow.childNodes.length: "+b.childNodes.length);this.log("getRefFromAddPane: valueTextbox.refName: "+f.refName); this.log("getRefFromAddPane: valueTextbox.id: "+f.id);b=f.value.trim();this.log("getRefFromAddPane: paramName: "+a+"; paramVal: "+b);""!=a&&""!=b&&(c.params[a]=b)}c.update();this.log("Exiting getRefFromAddPane");return c},addReference:function(a){this.addNewElement(a);a.orig=a.toString();this.insertRefIntoMWEditBox(a,!0);a.save=!0;a.inMWEditBox=!0},clearCitePanes:function(a){a.hasChildNodes()&&a.removeChild(a.firstChild)},activateRemoveField:function(a){jQuery(".delete-field",a).click(function(){jQuery(a).hide("highlight", {},"slow",function(){jQuery(a).remove()})})},changeAddPane:function(a){jQuery("#add-fields").scrollTop(0);jQuery(a.parentNode).show();var c=jQuery(".addpanes",a.parentNode.parentNode).get(0);this.clearCitePanes(c);var b=a.value,d=document.getElementById("dummyCitePane").cloneNode(!0);d.id=b.replace(" ","_");jQuery(".ref-name-row",d).children("input").attr("id","addrefname");jQuery(".ref-name-row",d).children("label").attr("for","addrefname");a="citemenu"==a.id?new this.CiteReference({}):new this.CitationReference({}); a.type=b;var b=this.getDescriptions(),e=a.getDefaultParams().slice(0);e.sort(a.getSorter());for(var f=0;f<e.length;f++)a.params[e[f]]="";this.log("changeAddPane: newRef: "+a);e=[];for(j in a.params)e.push(j);e.sort(a.getSorter());for(var g=a.getRequiredParams(),i=jQuery(".paramlist",d)[0],f=0;f<e.length;f++){var j=e[f],h;if(b[j]){h=document.getElementById("preloadedparamrow").cloneNode(!0);var k=jQuery(".paramdesc",h);if(g[j]){k.addClass("required");var l=jQuery(".delete-field",h)[0];l.parentNode.removeChild(l)}else this.activateRemoveField(h); k.text(b[j]);k.attr("for",this.NEW_PARAM_PREFIX+j);"accessdate"==j&&jQuery(".paramvalue",h).val(this.formatDate(new Date))}else h=document.getElementById("addedparamrow").cloneNode(!0),jQuery(".paramdesc",h)[0].setAttribute("value",j);h.id="";this.activateRemoveField(h);jQuery(".paramvalue",h)[0].id=this.NEW_PARAM_PREFIX+j;this.log("changeAddPane: param: "+j+"; newRef.params[param]: "+a.params[j]);jQuery(h).show();i.appendChild(h)}jQuery(d).show();c.insertBefore(d,c.firstChild);this.log("Exiting changeAddPane")}, createGUI:function(){importStylesheetURI(this.JQUERYUI_STYLES_URL);importStylesheetURI(this.STATIC_BASE+"styles.css");var a=jQuery("<div/>",{id:"proveit"}),c=jQuery("<div/>",{id:"tabs"}),b=jQuery("<h1/>"),d=jQuery("<a/>",{title:"Created by the ELC Lab at Georgia Tech",href:"http://proveit.cc.gatech.edu",target:"_blank"}),e=jQuery("<img/>",{src:this.STATIC_BASE+"logo.png",alt:"ProveIt",height:30,width:118});d.append(e);b.append(d);var f=jQuery("<button/>",{text:"show/hide"});b.append(f);c.append(b); e=jQuery("<ul/>");d=jQuery("<li/>");b=jQuery("<a/>",{id:"view-link","class":"tab-link",href:"#view-tab"});b.append("References (");var g=jQuery("<span/>",{id:"numRefs"}).append("0");b.append(g).append(")");d.append(b);e.append(d);g=jQuery("<li/>");d=jQuery("<a/>",{id:"add-link","class":"tab-link",href:"#add-tab"}).append("Add a Reference");g.append(d);e.append(g);c.append(e);var i=jQuery("<div/>",{id:"view-tab",css:{display:"none"}}),e=jQuery("<div/>",{id:"view-pane"}),g=jQuery("<div/>",{"class":"scroll", style:"height: 210px;"}),j=jQuery("<table/>",{id:"refs"}),h=jQuery("<tr/>",{id:"dummyRef",style:"display: none;"});h.append(jQuery("<td/>",{"class":"number"})).append(jQuery("<td/>",{"class":"type"})).append(jQuery("<td/>",{"class":"title"}));var k=jQuery("<td/>",{"class":"edit"}).append(jQuery("<button/>",{text:"edit"}));h.append(k);j.append(h);g.append(j);e.append(g);i.append(e);k=jQuery("<div/>",{id:"edit-pane",style:"display: none"});e=jQuery("<div/>",{id:"edit-fields","class":"inputs scroll", style:"height: 170px",tabindex:0});h=jQuery("<div/>",{"class":"ref-name-row",tabindex:-1});g=jQuery("<label/>",{"for":"editrefname",title:"This is a unique identifier that can be used to refer to this reference elsewhere on the page.","class":"paramdesc"}).append("&lt;ref&gt; name");h.append(g);h.append(jQuery("<input/>",{id:"editrefname","class":"paramvalue"}));g=jQuery("<div/>",{"class":"paramlist"});e.append(h);e.append(g);k.append(e);var l=jQuery("<div/>",{id:"edit-buttons"}),e=jQuery("<button/>", {style:"margin-right: 50px;"}).append("add field");l.append(e);e=jQuery("<span/>",{"class":"required",text:"bold"});l.append(e).append(" = required field");g=jQuery("<button/>",{"class":"right-side accept",text:"update edit form"});l.append(g);j=jQuery("<button/>",{"class":"right-side cancel",text:"cancel"});l.append(j);k.append(l);i.append(k);c.append(i);k=jQuery("<div/>",{id:"dummyCitePane","class":"typepane",style:"display: none"});h=h.clone();k.append(h);k.append(jQuery("<div/>",{"class":"paramlist"})); c.append(k);h=jQuery("<div/>",{id:"preloadedparamrow","class":"preloadedrow input-row",style:"display: none"}).append(jQuery("<label/>",{"class":"paramdesc"}));k=jQuery("<input/>",{"class":"paramvalue",tabindex:-1});h.append(k);l=jQuery("<button/>",{"class":"delete-field"}).append("delete field");h.append(l);c.append(h);h=jQuery("<div/>",{id:"addedparamrow","class":"addedrow input-row",style:"display: none"}).append(jQuery("<input/>",{"class":"paramdesc",tabindex:-1})).append(k.clone()).append(l.clone()); c.append(h);var p=jQuery("<div/>",{id:"add-tab",css:{display:"none"}}),h=jQuery("<div/>",{id:"add-fields","class":"inputs scroll",style:"height: 170px"}),n=jQuery("<div/>",{style:"display: none",id:"cite","class":"input-row"}),m=jQuery("<label/>",{"for":"citemenu","class":"paramdesc required",text:"Reference type"});n.append(m);for(var q=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(q.get(0))}}),o=this.CiteReference.getTypes(),k=this.getDescriptions(),l=0;l<o.length;l++)q.append(jQuery("<option/>", {value:o[l],text:k[o[l]]}));n.append(q);h.append(n);h.append(jQuery("<div/>",{"class":"addpanes",id:"citepanes",tabindex:0}));n=jQuery("<div/>",{style:"display: none",id:"citation","class":"input-row"});m=m.clone().attr("for","citationmenu");n.append(m);for(var r=jQuery("<select/>",{id:"citemenu",change:function(){proveit.changeAddPane(r.get(0))}}),m="web,book,journal,encyclopedia,news,patent".split(","),o=0;o<m.length;o++)r.append(jQuery("<option/>",{value:m[l],text:k[m[l]]}));n.append(r);h.append(n).append(jQuery("<div/>", {"class":"addpanes",id:"citationpanes",style:"display: none;"}));p.append(h);h=jQuery("<div/>",{id:"add-buttons"});h.append(jQuery("<button/>",{style:"margin-right: 50px;",text:"add field"})).append(e.clone()).append(" = required").append(g.clone().text("insert into edit form")).append(j.clone());p.append(h);c.append(p);a.append(c);jQuery(document.body).prepend(a);var s=function(){jQuery("#edit-pane").hide();jQuery("#view-pane").show()};jQuery("#tabs").tabs({selected:0,show:function(a,b){switch(b.index){case 1:s(), proveit.changeAddPane(document.getElementById(proveit.togglestyle?"citemenu":"citationmenu"))}}});jQuery(b).click(function(){jQuery(i).is(":hidden")?f.click():s()});jQuery(d).click(function(){jQuery(p).is(":hidden")&&f.click()});jQuery("#add-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(document.getElementById("add-tab"))}).next().next().button({icons:{primary:"ui-icon-circle-check",secondary:"ui-icon-circle-arrow-e"}}).click(function(){proveit.addReference(proveit.getRefFromAddPane(jQuery("#add-tab .typepane").get(0))); jQuery("#tabs").tabs({selected:"#view-tab"});jQuery("div.scroll, #view-pane").scrollTop(1E5)}).next().button({icons:{primary:"ui-icon-circle-close"}}).click(function(){jQuery("#tabs").tabs({selected:"#view-tab"})});jQuery("button.cancel").click(s);jQuery("#edit-buttons button:first").button({icons:{primary:"ui-icon-circle-plus"}}).click(function(){proveit.addPaneRow(jQuery("#edit-pane"))}).next().next().button({icons:{primary:"ui-icon-circle-check"}}).next().button({icons:{primary:"ui-icon-circle-close"}}); jQuery(".delete-field").button({icons:{primary:"ui-icon-close"},text:!1});f.button({icons:{primary:"ui-icon-triangle-1-n"},text:!1});var t=jQuery("#view-tab, #add-tab");f.toggle(function(){t.show();f.button("option","icons",{primary:"ui-icon-triangle-1-s"})},function(){t.hide();f.button("option","icons",{primary:"ui-icon-triangle-1-n"})});this.scanForRefs();this.loadMaximized&&f.click();jQuery("#refs tr").eq(0).click().click();jQuery("#refs tr:even").addClass("light");jQuery("#refs tr:odd").addClass("dark")}, makeRefBoxRow:function(a,c){var b=jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0);a.isValid()||jQuery(b).addClass("invalid");jQuery(".edit button",b).get(0);var d=this,e="",f="";null!=a.params.title&&(e=a.params.title,f=this.truncateTitle(e));jQuery("td.title",b).text(f);jQuery("td.title",b).attr("title",e);e="";a.params.year?e=a.params.year:a.params.date&&(f=a.params.date.match(/^([12]\d{3})/))&&(e=f[1]);var g="";a.params.author? g=a.params.author:a.params.last&&(g=a.params.last);if(a.params.coauthors||a.params.last2)g+=" <i>et al.</i>";var i=a.getIcon(),j="",f=a.type;switch(f){case "web":j=a.params.url;break;case "book":null!=a.params.isbn&&(j=wgServer+"/w/index.php?title=Special%3ABookSources&isbn="+a.params.isbn);break;case "journal":case "conference":null!=a.params.doi&&(j="http://dx.doi.org/"+a.params.doi);break;case "news":j=a.params.url;break;case "episode":j="http://www.imdb.com/find?s=ep&q="+escape(a.params.title)}jQuery("td.type", b).css("background-image","url("+i+")");jQuery("td.type",b).attr("title",a.type);var h=i="",k="";""!=g&&(i='By: <span class="author">'+g+"</span>");""!=e&&(h='Date: <span class="date">'+e+"</span>");null!=f&&(""!=j&&(f='<a href="'+j+'" target="_blank">'+f+"</a>"),k='Type: <span class="type">'+f+"</span>");g="";"raw"==f?g=k+" | "+a.toString():""!=i?g=""!=h?""!=k?i+" | "+h+" | "+k:i+" | "+h:""!=k?i+" | "+k:i:""!=h?g=""!=k?h+" | "+k:h:""!=k&&(g=k);g="<p>"+g+"</p>";e=jQuery("<div />",{"class":"expanded"}); jQuery(e).append(g);jQuery("td.title",b).append(e);c||(f=jQuery("#refs tr").length,jQuery("td.number",b).text(f),jQuery("#numRefs").text(f));jQuery(b).click(function(){d.highlightTargetString(a.orig);jQuery("#refs tr").removeClass("selected");jQuery(b).addClass("selected")});for(var f=function(){d.updateEditPane(a);jQuery("#view-pane").hide();jQuery("#edit-pane").show()},l=a.getCitationStrings(),g=jQuery('<span class="all-citations" />'),j=0;j<l.length;j++){i=j+1;for(h="";0<i;)k=--i%26,h=String.fromCharCode(97+ k)+h,i=Math.floor(i/26);i=jQuery('<a href="#">'+h+"</a>");h=function(a){return function(){for(var b=0,c=0,d=proveit.getMWEditValue(),c=0;c<a;c++){b=d.indexOf(l[c],b);if(-1==b)return proveit.log("citationStrings["+c+"]: "+l[c]+" not found. Returning."),!1;b+=l[c].length}b=d.indexOf(l[a],b);-1==b?proveit.log("citationStrings["+a+"]: "+l[a]+" not found."):proveit.highlightLengthAtIndex(b,l[a].length);return!1}}(j);i.click(h);g.append(i)}1<l.length&&(j=jQuery("<p />"),j.append('This reference is cited in the article <span class="num-citations">'+ l.length+" times</span>: ").append(g),e.append(j));"raw"!=a.type?(g=jQuery("<button />",{text:"edit"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!1}),g.click(f),jQuery(".edit",b).append(g),g=jQuery("<button />",{"class":"edit",text:"edit this reference"}),jQuery(g).button({icons:{primary:"ui-icon-pencil"},text:!0}),g.click(f),e.append(g),jQuery(b).dblclick(f)):jQuery(".edit",b).append("&nbsp;");0<l.length&&(f=jQuery("<button />",{"class":"insert",text:"insert this reference at cursor"}), jQuery(f).button({icons:{primary:"ui-icon-arrowthick-1-e"},text:!0}),f.click(function(){d.insertRefIntoMWEditBox(a,!1);return!1}),e.append(f));return b},truncateTitle:function(a){var c=a;86<a.length&&(c=c.substring(0,86),a=c.lastIndexOf(" "),-1!=a&&(c=c.substr(0,a),c+=" ..."));return c},formatDate:function(a){var c=a.getFullYear(),b=this.getDescriptions().months[a.getMonth()],a=(10>a.getDate()?"0":"")+a.getDate();return b+" "+a+", "+c},addNewElement:function(a){var c=this.getRefBox();jQuery(c).append(this.makeRefBoxRow(a, !1))}},window.proveit);proveit.CiteReference.getTypes=function(){return"web,book,journal,conference,encyclopedia,news,newsgroup,press release,interview,episode,video".split(",")};String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")});proveit.split._compliantExecNpcg=void 0===/()??/.exec("")[1];proveit.split._nativeSplit=String.prototype.split;proveit.load(); 6c08ob34cipg122kecx0ag4j5dtj91y 360736 360735 2012-03-04T03:32:31Z en>Mattflaschen 0 Deploy commit d2745c478647 of ProveIt. 360736 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * Imported from Mercurial commit d2745c478647 as of 2012-03-04 from http://code.google.com/p/proveit-js/ * Changes should be made through our Google Code project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "http://proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === 'object' && console.log) { console.log("[ProveIt] %o", msg); } }, /** * Returns true if we are on a known domain, and the action is set to edit or submit * @return {Boolean} true if page is supported, false otherwise */ isSupportedEditPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). Also, must be edit or preview mode return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox') && (wgAction == 'edit' || wgAction == 'submit'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * Keep ProveIt maximized on load. If false, it will start minimized. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; /* else { this.log("ProveIt already in summary."); } */ }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } /* else { this.log("Not adding to summary."); this.log("this.shouldAddSummary: " + this.shouldAddSummary); this.log("this.prefs.getBoolPref(\"shouldAddSummary\"): " + this.prefs.getBoolPref("shouldAddSummary")); } */ }, /* * onload and onunload event handlers tied to the sidebar. These tie the * event handler into the browser and remove it when finished. */ /** * Runs to create GUI if we're on a supported edit page * @return {Boolean} true if GUI was created, false if it already existed, or it's not a supported edit page */ load : function() { this.summaryFunctionAdded = false; if($('#' + this.GUI_ID).length > 0) { // GUI already created return false; } if(this.isSupportedEditPage()) { addOnloadHook(function() { proveit.createGUI(); }); return true; } return false; }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.log("Entering acceptEdit"); proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); acceptButton.unbind('click', acceptEdit); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.click(acceptEdit); jQuery('.tab-link').one('click', function() { acceptButton.unbind('click', acceptEdit); }); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: this.GUI_ID}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) showHideButton.click(); // We use click so toggle stays in a consistent state. else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) showHideButton.click(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.scanForRefs(); if(this.loadMaximized) { showHideButton.click(); } jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.load(); // Local Variables: // js2-basic-offset: 8 // End: d93u4qiuufpl2bqffzeqbf5z39fzq5o 360737 360736 2012-03-04T03:36:57Z en>Mattflaschen 0 Deploy commit dce6753d7d50 of ProveIt. 360737 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * Imported from Mercurial commit dce6753d7d50 as of 2012-03-01 from http://code.google.com/p/proveit-js/ * Changes should be made through our Google Code project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "http://proveit-js.googlecode.com/hg/static/", /** * URL to jQueryUI script * @type String */ JQUERYUI_SCRIPT_URL : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js", /** * URL to jQueryUI stylesheet * @type String */ JQUERYUI_STYLES_URL : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/themes/base/jquery-ui.css", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === 'object' && console.log) { console.log("[ProveIt] %o", msg); } }, /** * Returns true if we are on a known domain, and the action is set to edit or submit * @return {Boolean} true if page is supported, false otherwise */ isSupportedEditPage : function() { // "Regular" article or Wikipedia:Sandbox (exception for testing). Also, must be edit or preview mode return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox') && (wgAction == 'edit' || wgAction == 'submit'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * Keep ProveIt maximized on load. If false, it will start minimized. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; /* else { this.log("ProveIt already in summary."); } */ }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } /* else { this.log("Not adding to summary."); this.log("this.shouldAddSummary: " + this.shouldAddSummary); this.log("this.prefs.getBoolPref(\"shouldAddSummary\"): " + this.prefs.getBoolPref("shouldAddSummary")); } */ }, /* * onload and onunload event handlers tied to the sidebar. These tie the * event handler into the browser and remove it when finished. */ /** * Runs to see if we want to load ProveIt * @return {Boolean} always true */ load : function() { this.summaryFunctionAdded = false; if(this.isSupportedEditPage()) { jQuery.getScript(proveit.JQUERYUI_SCRIPT_URL, function() { addOnloadHook(function() { proveit.createGUI(); }); }); } return true; }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.log("Entering acceptEdit"); proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); acceptButton.unbind('click', acceptEdit); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.click(acceptEdit); jQuery('.tab-link').one('click', function() { acceptButton.unbind('click', acceptEdit); }); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { // Keep jQuery UI CSS version in sync with JS above. importStylesheetURI(this.JQUERYUI_STYLES_URL); importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: 'proveit'}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) showHideButton.click(); // We use click so toggle stays in a consistent state. else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) showHideButton.click(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.scanForRefs(); if(this.loadMaximized) { showHideButton.click(); } jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.load(); // Local Variables: // js2-basic-offset: 8 // End: 5guxhkgv0hearby2tjk5h2g5in9u9jg 360738 360737 2012-03-04T04:31:50Z en>Mattflaschen 0 Deploy commit 281a01f6fd84 of ProveIt. 360738 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * Imported from Mercurial commit 281a01f6fd84 as of 2012-03-04 from http://code.google.com/p/proveit-js/ * Changes should be made through our Google Code project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "http://proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === 'object' && console.log) { console.log("[ProveIt] %o", msg); } }, /** * Returns true if we are on a known domain, and the action is set to edit or submit * @return {Boolean} true if page is supported, false otherwise */ isSupportedEditPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). Also, must be edit or preview mode return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox') && (wgAction == 'edit' || wgAction == 'submit'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * Keep ProveIt maximized on load. If false, it will start minimized. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; /* else { this.log("ProveIt already in summary."); } */ }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } /* else { this.log("Not adding to summary."); this.log("this.shouldAddSummary: " + this.shouldAddSummary); this.log("this.prefs.getBoolPref(\"shouldAddSummary\"): " + this.prefs.getBoolPref("shouldAddSummary")); } */ }, /* * onload and onunload event handlers tied to the sidebar. These tie the * event handler into the browser and remove it when finished. */ /** * Runs to create GUI if we're on a supported edit page * @return {Boolean} true if GUI was created, false if it already existed, or it's not a supported edit page */ load : function() { this.summaryFunctionAdded = false; if($('#' + this.GUI_ID).length > 0) { // GUI already created return false; } if(this.isSupportedEditPage()) { addOnloadHook(function() { var dependency = 'jquery.ui.tabs'; mw.loader.using(dependency, function() { proveit.createGUI(); }, function() { proveit.log('Failed to load ' + dependency); }); }); return true; } return false; }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.log("Entering acceptEdit"); proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); acceptButton.unbind('click', acceptEdit); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.click(acceptEdit); jQuery('.tab-link').one('click', function() { acceptButton.unbind('click', acceptEdit); }); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: this.GUI_ID}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) showHideButton.click(); // We use click so toggle stays in a consistent state. else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) showHideButton.click(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.scanForRefs(); if(this.loadMaximized) { showHideButton.click(); } jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.load(); // Local Variables: // js2-basic-offset: 8 // End: sahf010ygeao5aig9oz9lzt2ig8o7ir 360739 360738 2012-03-08T04:27:49Z en>Mattflaschen 0 Deploy commit 2497a35552a3 of ProveIt. 360739 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * Imported from Mercurial commit 2497a35552a3 as of 2012-03-08 from http://code.google.com/p/proveit-js/ * Changes should be made through our Google Code project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "http://proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === 'object' && console.log) { console.log("[ProveIt] %o", msg); } }, /** * Returns true if we are on a known domain, and the action is set to edit or submit * @return {Boolean} true if page is supported, false otherwise */ isSupportedEditPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). Also, must be edit or preview mode return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox') && (wgAction == 'edit' || wgAction == 'submit'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * Keep ProveIt maximized on load. If false, it will start minimized. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; /* else { this.log("ProveIt already in summary."); } */ }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } /* else { this.log("Not adding to summary."); this.log("this.shouldAddSummary: " + this.shouldAddSummary); this.log("this.prefs.getBoolPref(\"shouldAddSummary\"): " + this.prefs.getBoolPref("shouldAddSummary")); } */ }, /* * onload and onunload event handlers tied to the sidebar. These tie the * event handler into the browser and remove it when finished. */ /** * Runs to create GUI if we're on a supported edit page * @return {Boolean} true if GUI was created, false if it already existed, or it's not a supported edit page */ load : function() { this.summaryFunctionAdded = false; if($('#' + this.GUI_ID).length > 0) { // GUI already created return false; } if(this.isSupportedEditPage()) { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.effects.highlight']; mw.loader.using(dependencies, function() { proveit.createGUI(); }, function() { proveit.log('Failed to load one of: ' + dependencies); }); }); return true; } return false; }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.log("Entering acceptEdit"); proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); acceptButton.unbind('click', acceptEdit); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.click(acceptEdit); jQuery('.tab-link').one('click', function() { acceptButton.unbind('click', acceptEdit); }); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: this.GUI_ID}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) showHideButton.click(); // We use click so toggle stays in a consistent state. else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) showHideButton.click(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.scanForRefs(); if(this.loadMaximized) { showHideButton.click(); } jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.load(); // Local Variables: // js2-basic-offset: 8 // End: 2438chbg18q1b8b80fsup0f65677ook 360740 360739 2012-03-28T04:14:04Z en>Mattflaschen 0 Deploy commit 428a1b285607 of ProveIt. 360740 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * Imported from Mercurial commit 428a1b285607 as of 2012-03-28 from http://code.google.com/p/proveit-js/ * Changes should be made through our Google Code project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "http://proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === 'object' && console.log) { console.log("[ProveIt] %o", msg); } }, /** * Returns true if we are on a known domain, and the action is set to edit or submit * @return {Boolean} true if page is supported, false otherwise */ isSupportedEditPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). Also, must be edit or preview mode return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox') && (wgAction == 'edit' || wgAction == 'submit'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * Keep ProveIt maximized on load. If false, it will start minimized. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; /* else { this.log("ProveIt already in summary."); } */ }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } /* else { this.log("Not adding to summary."); this.log("this.shouldAddSummary: " + this.shouldAddSummary); this.log("this.prefs.getBoolPref(\"shouldAddSummary\"): " + this.prefs.getBoolPref("shouldAddSummary")); } */ }, /* * onload and onunload event handlers tied to the sidebar. These tie the * event handler into the browser and remove it when finished. */ /** * Runs to create GUI if we're on a supported edit page * @return {Boolean} true if GUI was created, false if it already existed, or it's not a supported edit page */ load : function() { this.summaryFunctionAdded = false; if($('#' + this.GUI_ID).length > 0) { // GUI already created return false; } if(this.isSupportedEditPage()) { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.effects.highlight']; mw.loader.using(dependencies, function() { proveit.createGUI(); }, function() { proveit.log('Failed to load one of: ' + dependencies); }); }); return true; } return false; }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: this.GUI_ID}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) showHideButton.click(); // We use click so toggle stays in a consistent state. else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) showHideButton.click(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.scanForRefs(); if(this.loadMaximized) { showHideButton.click(); } jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.load(); // Local Variables: // js2-basic-offset: 8 // End: fy09jp5j9nhweppb58v2ep8a2v18z6w 360741 360740 2012-06-20T00:07:15Z en>Mattflaschen 0 Deploy commit 079c9022b846 of ProveIt. 360741 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * Imported from Mercurial commit 079c9022b846 as of 2012-06-20 from http://code.google.com/p/proveit-js/ * Changes should be made through our Google Code project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Copyright 2011 - * * Matthew Flaschen * * Atlanta, GA 30332-0415 * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "http://proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === 'object' && console.log) { console.log("[ProveIt] %o", msg); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage : function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible : true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton : function() { var $box = jQuery(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: 'http://upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup : function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load : function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.effects.highlight']; mw.loader.using(dependencies, function() { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } }, function() { proveit.log('Failed to load one of: ' + dependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: this.GUI_ID}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {jQueryNodeSet} */ viewAndAddPanes : null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {jQueryNode} root of ProveIt */ getGUI : function() { return jQuery('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide : function() { this.getGUI().hide(); }, /** * Show ProveIt */ show : function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility : function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility : null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); // Local Variables: // js2-basic-offset: 8 // End: 2408u6q6qstqir4d4wbfar3wcp8z931 360742 360741 2012-12-07T02:02:25Z en>Mattflaschen 0 Deploy commit 0130d6d08fc5 of ProveIt. 360742 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| * * ProveIt, Copyright 2008 - 2011 Georgia Tech Research Corporation, Copyright 2011 and later - Matthew Flaschen * Available under the GNU Free Documentation License, Creative Commons Attribution/Share-Alike License 3.0, and the GNU General Public License version 2 * * Imported from Mercurial commit 0130d6d08fc5 as of 2012-12-07 from http://code.google.com/p/proveit-js/ * This is a minified version. Changes should be made through that project. * * ProveIt is a powerful GUI tool for viewing, adding, editing, and inserting references. * See [[User:ProveIt GT]] for more information. */ /* * ProveIt (http://code.google.com/p/proveit-js/) is a new tool for reliable referencing on Wikipedia * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = jQuery.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER : "[ProveIt] ", /** * Convenience log function * @param {String} msg message to log */ log : function(msg) { if(typeof(console) === "object" && console.log) { console.log(this.LOG_MARKER + "%o", msg); } }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [this.LOG_MARKER, ex, ex.stack]; if(typeof(console) === "object") { if(console.error) { console.error.apply(null, args); } else if(console.log) { console.log.apply(null, args); } } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage : function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {jQueryNode} reference box */ getRefBox : function() { return jQuery("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } jQuery(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); var editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return jQuery("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return jQuery("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return jQuery("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible : true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton : function() { var $box = jQuery(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup : function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load : function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.effects.highlight']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ' + errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } var refs = jQuery("tr:not('tr#dummyRef')", box); jQuery(refs).remove(); }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = jQuery(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = jQuery("div.input-row", editPane); var refName = jQuery('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { // this.log(item + ":" + paramBoxes[item].id); //this.log("item: " + i); var paramRow = paramBoxes[i]; var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = valueTextbox.value.trim(); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { //this.log("Setting " + paramName + "= " + paramVal); ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = jQuery('.selected', this.getRefBox()).get(0); this.log('newRichItem: ' + newRichItem + ', oldRichItem: ' + oldRichItem + 'oldRichItem.parentNode: ' + oldRichItem.parentNode); var oldNumber = jQuery('td.number',oldRichItem).text(); jQuery('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); jQuery(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { jQuery('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { //this.log("Setting default blank parameter: defaults[i] = " + defaults[i]); tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { //this.log(item); paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ jQuery('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var i = 0; i < paramNames.length; i++) { //this.log("Calling addPaneRow on tempParams." + item); //this.log("i: " + i + ", paramNames[i]: " + paramNames[i]); this.addPaneRow(jQuery("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[i], required[paramNames[i]], true); } var acceptButton = jQuery('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, jQuery("#edit-pane").get()); proveit.saveRefFromEdit(ref); jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll jQuery('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = jQuery('#'+id).clone(); // clone the hidden row jQuery(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = jQuery('.paramdesc', newline).eq(0); var paramValue = jQuery('.paramvalue', newline).eq(0); jQuery('.paramlist', root).append(newline); if(req) // if field is required... { jQuery(paramName).addClass('required'); // visual indicator that label is required jQuery('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } jQuery(paramName).text(desc); jQuery(paramName).attr('title',item); jQuery(paramValue).val(params[item]); jQuery(newline).show(); } else { // added a new row, so make it fancy jQuery(newline).show('highlight',{},'slow'); jQuery('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { this.log("Entering scanForRefs."); // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { //this.log("currentScan[" + i + "]: " + currentScan[i]); var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); this.log("refText: " + refText + "; isReference: " + isReference); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } //this.log("scanForRefs: workingstring: " + workingstring); var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = cutupstring[0].substring(typestart + 1, typeend).trim(); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = names[j].trim().replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = values[j].trim(); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText proveit.log("Updating " + strings[i] + " to " + newCiteText); strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. proveit.log("Adding " + newCiteText + " to citationStrings"); strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { proveit.log("getInsertionText"); if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return jQuery.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = jQuery('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = jQuery(".paramlist", box)[0]; var paramRows = jQuery('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; this.log("getRefFromAddPane: i: " + i + ", paramRow: " + paramRow); var valueTextbox = jQuery(".paramvalue", paramRow)[0]; if(jQuery(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = jQuery(".paramdesc", paramRow)[0].value.trim(); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } this.log("getRefFromAddPane: paramRow.childNodes.length: " + paramRow.childNodes.length); this.log("getRefFromAddPane: valueTextbox.refName: " + valueTextbox.refName); this.log("getRefFromAddPane: valueTextbox.id: " + valueTextbox.id); paramVal = valueTextbox.value.trim(); this.log("getRefFromAddPane: paramName: " + paramName + "; paramVal: " + paramVal); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); this.log("Exiting getRefFromAddPane"); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { jQuery('.delete-field', fieldRow).click(function() { jQuery(fieldRow).hide( 'highlight',{},'slow', function() { jQuery(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { //this.log("menu.id: " + menu.id); // Reset scroll jQuery('#add-fields').scrollTop(0); jQuery(menu.parentNode).show(); // cite/citation vbox. var citePanes = jQuery(".addpanes", menu.parentNode.parentNode).get(0); //this.log("citePanes: " + citePanes); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row jQuery('.ref-name-row',genPane).children('input').attr('id','addrefname'); jQuery('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } this.log("changeAddPane: newRef: " + newRef); // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = jQuery(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = jQuery('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); // Use raw DOM calls to work-around issue 79 var del = jQuery('.delete-field', paramBox)[0]; del.parentNode.removeChild(del); // don't let people remove required fields // jQuery('.delete-field', paramBox).remove(); } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') jQuery('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = jQuery(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); jQuery(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; this.log("changeAddPane: param: " + param + "; newRef.params[param]: " + newRef.params[param]); //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? jQuery(paramBox).show(); paramList.appendChild(paramBox); } jQuery(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); this.log("Exiting changeAddPane"); }, /** * Create ProveIt HTML GUI */ createGUI : function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = jQuery('<div/>', {id: this.GUI_ID}); var tabs = jQuery('<div/>', {id: 'tabs'}); var created = jQuery('<h1/>'); var createdLink = jQuery('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = jQuery('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = jQuery('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = jQuery('<ul/>'); var view = jQuery('<li/>'); // View tab link var viewLink = jQuery('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = jQuery('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = jQuery('<li/>'); // Add tab link var addLink = jQuery('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = jQuery('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = jQuery('<div/>', {id: 'view-pane'}); var viewScroll = jQuery('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = jQuery('<table/>', {id: 'refs'}); var dummyRef = jQuery('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append(jQuery('<td/>', {"class": 'number'})). append(jQuery('<td/>', {"class": 'type'})). append(jQuery('<td/>', {"class": 'title'})); //append(jQuery('<td/>', {"class": 'details'})); var editTd = jQuery('<td/>', {"class": 'edit'}). append(jQuery('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = jQuery('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = jQuery('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: 0}); // div.ref-name-row var refNameRow = jQuery('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = jQuery('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append(jQuery('<input/>', {id: 'editrefname', "class": 'paramvalue'})); // div.paramlist var paramList = jQuery('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = jQuery('<div/>', {id: 'edit-buttons'}); var addFieldButton = jQuery('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = jQuery('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = jQuery('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = jQuery('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = jQuery('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //jQuery('input', addRefNameRow).attr('id', 'addrefname'); //jQuery('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append(jQuery('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = jQuery('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append(jQuery('<label/>', {"class": 'paramdesc'})); var paramvalue = jQuery('<input/>', {"class": 'paramvalue', tabindex: -1}); preloadedparam.append(paramvalue); var deleteButton = jQuery('<button/>', {"class": 'delete-field'}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = jQuery('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append(jQuery('<input/>', {"class": 'paramdesc', tabindex: -1})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = jQuery('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = jQuery('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = jQuery('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = jQuery('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append(jQuery('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append(jQuery('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: 0})); var citation = jQuery('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = jQuery('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append(jQuery('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append(jQuery('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = jQuery('<div/>', {id: 'add-buttons'}); addButtons.append(jQuery('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); jQuery(document.body).prepend(gui); var cancelEdit = function() { jQuery("#edit-pane").hide(); jQuery("#view-pane").show(); }; // set up tabs jQuery("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //jQuery('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // jQuery('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs jQuery(viewLink).click(function(){ if(jQuery(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); jQuery(addLink).click(function(){ if(jQuery(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons jQuery("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane(jQuery('#add-tab .typepane').get(0))); jQuery("#tabs").tabs( { selected: '#view-tab' } ); jQuery("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { jQuery("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons jQuery("button.cancel").click(cancelEdit); // edit panel buttons jQuery("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(jQuery("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button jQuery(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = jQuery("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); jQuery("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors jQuery("#refs tr:even").addClass('light'); jQuery("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {jQueryNodeSet} */ viewAndAddPanes : null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {jQueryNode} root of ProveIt */ getGUI : function() { return jQuery('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide : function() { this.getGUI().hide(); }, /** * Show ProveIt */ show : function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility : function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility : null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = jQuery('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. jQuery(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = jQuery('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } jQuery('td.title', newchild).text(shortTitle); jQuery('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //jQuery('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // jQuery('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } jQuery('td.type', newchild).css('background-image','url('+icon+')'); jQuery('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = jQuery('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box jQuery(expanded).append(byline); // append the expanded info box to the title <td> jQuery('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = jQuery('#refs tr').length; jQuery('td.number', newchild).text(numRefs); jQuery('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) jQuery(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); jQuery("#refs tr").removeClass('selected'); jQuery(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); jQuery("#view-pane").hide(); jQuery("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = jQuery('.pointers', newchild); var allCitations = jQuery('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = jQuery('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = jQuery('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = jQuery('<button />',{ text: 'edit' }); // transform button jQuery(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button jQuery('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = jQuery('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button jQuery(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER jQuery(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height jQuery('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = jQuery('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button jQuery(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); jQuery(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; if(!String.prototype.trim) { /** * Generic trim function, trims all leading and trailing whitespace. * @for proveit * @return {String} the trimmed string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); }; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); // Local Variables: // js2-basic-offset: 8 // End: 2seu9xatn5t5tsibfturc1a7x684plh 360743 360742 2012-12-13T06:03:15Z en>Mattflaschen 0 Deploy commit fc855f317561 of ProveIt. 360743 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit fc855f317561 as of 2012-12-13 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER : "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log : function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage : function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox : function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible : true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton : function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup : function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load : function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = $.trim(cutupstring[0].substring(typestart + 1, typeend)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row $('.ref-name-row',genPane).children('input').attr('id','addrefname'); $('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); }, /** * Create ProveIt HTML GUI */ createGUI : function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px'}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes : null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI : function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide : function() { this.getGUI().hide(); }, /** * Show ProveIt */ show : function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility : function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility : null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); $('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); // Local Variables: // js2-basic-offset: 8 // End: 86477vvpj8c6wtqhp2bgq2axjc9wh1c 360744 360743 2012-12-13T06:48:10Z en>Mattflaschen 0 Deploy commit 5b4a7790c53f of ProveIt. 360744 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit 5b4a7790c53f as of 2012-12-13 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER : "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log : function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage : function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox : function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible : true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton : function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup : function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load : function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = $.trim(cutupstring[0].substring(typestart + 1, typeend)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row $('.ref-name-row',genPane).children('input').attr('id','addrefname'); $('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); }, /** * Create ProveIt HTML GUI */ createGUI : function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes : null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI : function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide : function() { this.getGUI().hide(); }, /** * Show ProveIt */ show : function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility : function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility : null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); $('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); // Local Variables: // js2-basic-offset: 8 // End: p068uyad0s71e5njl4atlk0hlw2mezs 360745 360744 2013-01-02T06:41:55Z en>Mattflaschen 0 Deploy commit 53890c809d10 of ProveIt. 360745 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit 53890c809d10 as of 2013-01-02 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE: "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = $.trim(cutupstring[0].substring(typestart + 1, typeend)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for AV Media it currently returns Audiovisual work. * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "page_white_world.png", book: "book.png", journal: "page_white_text.png", news: "newspaper.png", newsgroup: "comments.png", "press release": "transmit_blue.png", interview: "telephone.png", episode: "television.png", "AV media": "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row $('.ref-name-row',genPane).children('input').attr('id','addrefname'); $('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate: function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); // Local Variables: // js2-basic-offset: 8 // End: pi0rq5nu10ksfa8wr18tkur7a212m3k 360746 360745 2013-01-02T07:16:05Z en>Mattflaschen 0 Deploy commit 5b4a7790c53f of ProveIt. 360746 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit 5b4a7790c53f as of 2012-12-13 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT : 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG : "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX : "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX : "editparam", GUI_ID : "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE : "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", video: "Video", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Finnish translation by Olli (ollinpostit at gmail.com) fi : { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions : function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER : "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log : function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage : function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage : function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox : function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition : function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex : function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString : function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox : function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue : function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm : function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit : function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary : function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded : false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary : true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible : true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized : false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary : function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton : function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup : function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load : function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox : function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox : function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane : function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit : function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane : function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow : function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle : true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert : false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split : function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals : function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs : function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX : /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef : function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var typestart = cutupstring[0].toLowerCase().indexOf('e'); // First end curly brace var rightcurly = cutupstring[0].indexOf('}'); // Usually, rightcurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeend = rightcurly != -1 ? rightcurly : cutupstring[0].length; // grab the type, then trim it. var type = $.trim(cutupstring[0].substring(typestart + 1, typeend)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference : function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference : function(argObj) { /* Mostly an identity mapping, except for redirects. I think * having the self-mappings is better than some kind of special case array. */ var typeNameMappings = { web:"web", book:"book", journal:"journal", conference:"conference", encyclopedia:"encyclopedia", news:"news", newsgroup:"newsgroup", paper:"journal", "press release":"press release", "pressrelease":"press release", interview:"interview", episode:"episode", video:"video" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web : { "url": true, "title": true}, book : { "title": true }, journal : { "title": true }, conference : { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup : { "title": true }, "press release" : { "title": true }, interview: { "last" : true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode : { "title": true }, video : { "title" : true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book : [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages" ], journal : [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference : [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup : [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview : ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode : ["title", "series", "credits", "airdate", "city", "network", "season"], video : ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web : "page_white_world.png", book : "book.png", journal : "page_white_text.png", news : "newspaper.png", newsgroup : "comments.png", "press release" : "transmit_blue.png", interview : "telephone.png", episode : "television.png", video : "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference : function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web : [ "url", "author", "title", "date", "accessdate"], news : [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia : ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book : ["author", "title", "publisher", "place", "year"], journal : ["author", "title", "journal", "volume", "issue", "year", "pages"], patent : ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference : function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane : function(box) { // get this working, lots of typing here. var type = box.id; // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference : function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes : function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField : function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane : function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); genPane.id = newRefType.replace(' ', '_'); // name the ref-name-row $('.ref-name-row',genPane).children('input').attr('id','addrefname'); $('.ref-name-row',genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $(genPane).show(); citePanes.insertBefore(genPane, citePanes.firstChild); }, /** * Create ProveIt HTML GUI */ createGUI : function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes : null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI : function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide : function() { this.getGUI().hide(); }, /** * Show ProveIt */ show : function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility : function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility : null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow : function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); $('td.type', newchild).attr('title',ref.type); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { if(url != '') refType = '<a href="' + url + '" target="_blank">' + refType + '</a>'; refTypeByline = 'Type: <span class="type">' + refType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + ref.toString(); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle : function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate : function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement : function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "video"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); // Local Variables: // js2-basic-offset: 8 // End: p068uyad0s71e5njl4atlk0hlw2mezs 360747 360746 2013-03-01T07:32:48Z en>Mattflaschen 0 Deploy commit c390bf9f532a of ProveIt. 360747 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit c390bf9f532a as of 2013-03-01 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE: "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "page_white_world.png", book: "book.png", journal: "page_white_text.png", news: "newspaper.png", newsgroup: "comments.png", "press release": "transmit_blue.png", interview: "telephone.png", episode: "television.png", "AV media": "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $genPane.show(); $(citePanes).prepend($genPane); }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } importStylesheetURI(this.STATIC_BASE + 'styles.css'); // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate: function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: jkrjacvj94cuv6bh70uoyoqkebxqh3a 360748 360747 2013-03-19T05:20:19Z en>Mattflaschen 0 Deploy commit 4fac8de711fd of ProveIt. 360748 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit 4fac8de711fd as of 2013-03-11 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE: "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "page_white_world.png", book: "book.png", journal: "page_white_text.png", news: "newspaper.png", newsgroup: "comments.png", "press release": "transmit_blue.png", interview: "telephone.png", episode: "television.png", "AV media": "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $genPane.show(); $(citePanes).prepend($genPane); }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as Monthname DD, YYYY * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate: function(date1) { var year = date1.getFullYear(); var month = this.getDescriptions().months[date1.getMonth()]; var day = (date1.getDate() < 10 ? '0' : '') + date1.getDate(); return month + ' ' + day + ', ' + year; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: 76o999jexgpxk5g7l21q6xmfivakizr 360749 360748 2013-04-07T02:07:40Z en>Mattflaschen 0 Deploy commit e7068ab5c391 of ProveIt. 360749 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit e7068ab5c391 as of 2013-04-07 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE: "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus", months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'] } }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "page_white_world.png", book: "book.png", journal: "page_white_text.png", news: "newspaper.png", newsgroup: "comments.png", "press release": "transmit_blue.png", interview: "telephone.png", episode: "television.png", "AV media": "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ].indexOf(param); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.formatDate(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $genPane.show(); $(citePanes).prepend($genPane); }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Formats date as YYYY-MM-DD * @param {Date} date1 date to format * @return {String} formatted date as String */ formatDate: function(date1) { return date1.getFullYear() + '-' + (date1.getMonth() < 9 ? '0' : '') + (date1.getMonth() + 1) + '-' + (date1.getDate() < 10 ? '0' : '') + date1.getDate(); }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: nrzyokuux4boifcd7h2hh37elzz44fw 360750 360749 2013-06-30T02:15:23Z en>Mattflaschen 0 Deploy commit c978344be3df of ProveIt. 360750 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit c978344be3df as of 2013-06-30 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE: "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus" } }, /** * Optional preference to specify default date format for new references. * If set, it overrides the general date preference from Special:Preferences. * * @type {String} supported date format string */ dateFormatString: null, /** * Singleton used to format dates according to user preference * * @type DateFormatter */ dateFormatter: null, /** * Gets the effective preference for date format. If there is no ProveIt-specific * preference already at proveit.dateFormatString, it will determine the correct preference * from MW user preferences. Then, it will store that value to proveit.dateFormatString * * @return {String} format string to use for dates */ getDatePreference: function () { if (this.dateFormatString === null) { this.dateFormatString = mw.user.options.get('date'); } return this.dateFormatString; }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; var preference = proveit.getDatePreference(); proveit.dateFormatter = new proveit.DateFormatter(preference); mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, // TODO: Use https://gerrit.wikimedia.org/r/#/c/67166/ when merged. /** * Date-formatting class * * @param {String} format one of the format strings supported by MW core. * Currently, the supported values are 'default', 'mdy', 'dmy', 'ymd', and 'ISO 8601'. * If an unknown value is passed, it will use wgDefaultDateFormat. */ DateFormatter: function (format) { // 1-indexed (due to filler item at 0), in page content language. var monthNames = mw.config.get('wgMonthNames'); var supportedFormats = ['mdy', 'dmy', 'ymd', 'ISO 8601']; if($.inArray(format, supportedFormats) === -1) { format = mw.config.get('wgDefaultDateFormat'); } function getMonthName(date) { return monthNames[date.getMonth() + 1];; } this.formatAsMdy = function(date) { return getMonthName(date) + ' ' + date.getDate() + ', ' + date.getFullYear(); }; this.formatAsDmy = function(date) { return date.getDate() + ' ' + getMonthName(date) + ' ' + date.getFullYear(); }; this.formatAsYmd = function(date) { return date.getFullYear() + ' ' + getMonthName(date) + ' ' + date.getDate(); }; this.formatAsISO8601 = function(date) { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate(); }; var formatters = { mdy: this.formatAsMdy, dmy: this.formatAsDmy, ymd: this.formatAsYmd, 'ISO 8601': this.formatAsISO8601 }; /** * Formats date according to stored preference * * @param {Date} date date to format * * @return {String} formatted date as String */ this.format = function(date) { return formatters[format](date); }; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "page_white_world.png", book: "book.png", journal: "page_white_text.png", news: "newspaper.png", newsgroup: "comments.png", "press release": "transmit_blue.png", interview: "telephone.png", episode: "television.png", "AV media": "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.dateFormatter.format(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $genPane.show(); $(citePanes).prepend($genPane); }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var tabs = $('<div/>', {id: 'tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button/>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link var viewLink = $('<a/>', {id: 'view-link', "class": 'tab-link', href: '#view-tab'}); viewLink.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewLink.append(numRefs). append(')'); view.append(viewLink); header.append(view); var add = $('<li/>'); // Add tab link var addLink = $('<a/>', {id: 'add-link', "class": 'tab-link', href: '#add-tab'}). append('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div/>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div/>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label/>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: iaqjcbynklzw3cg53ox3koienlgelrz 360751 360750 2014-06-12T03:08:12Z en>Krinkle 0 Clean up 360751 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Mercurial commit c978344be3df as of 2013-06-30 from http://code.google.com/p/proveit-js/ * Changes should be made through that Google Code project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /** * Base URL used for static content * * This directory includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James * @type String */ STATIC_BASE: "//proveit-js.googlecode.com/hg/static/", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus" } }, /** * Optional preference to specify default date format for new references. * If set, it overrides the general date preference from Special:Preferences. * * @type {String} supported date format string */ dateFormatString: null, /** * Singleton used to format dates according to user preference * * @type DateFormatter */ dateFormatter: null, /** * Gets the effective preference for date format. If there is no ProveIt-specific * preference already at proveit.dateFormatString, it will determine the correct preference * from MW user preferences. Then, it will store that value to proveit.dateFormatString * * @return {String} format string to use for dates */ getDatePreference: function () { if (this.dateFormatString === null) { this.dateFormatString = mw.user.options.get('date'); } return this.dateFormatString; }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { $(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; var preference = proveit.getDatePreference(); proveit.dateFormatter = new proveit.DateFormatter(preference); mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $(editPane).find("div.input-row"); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(paramRow).find(".paramvalue")[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(paramRow).find(".paramdesc")[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number', oldRichItem).text(); $('td.number', newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = []; for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').on('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc).attr('title', item); $(paramValue).val(params[item]); $(newline).show(); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, // TODO: Use https://gerrit.wikimedia.org/r/#/c/67166/ when merged. /** * Date-formatting class * * @param {String} format one of the format strings supported by MW core. * Currently, the supported values are 'default', 'mdy', 'dmy', 'ymd', and 'ISO 8601'. * If an unknown value is passed, it will use wgDefaultDateFormat. */ DateFormatter: function (format) { // 1-indexed (due to filler item at 0), in page content language. var monthNames = mw.config.get('wgMonthNames'); var supportedFormats = ['mdy', 'dmy', 'ymd', 'ISO 8601']; if($.inArray(format, supportedFormats) === -1) { format = mw.config.get('wgDefaultDateFormat'); } function getMonthName(date) { return monthNames[date.getMonth() + 1]; } this.formatAsMdy = function(date) { return getMonthName(date) + ' ' + date.getDate() + ', ' + date.getFullYear(); }; this.formatAsDmy = function(date) { return date.getDate() + ' ' + getMonthName(date) + ' ' + date.getFullYear(); }; this.formatAsYmd = function(date) { return date.getFullYear() + ' ' + getMonthName(date) + ' ' + date.getDate(); }; this.formatAsISO8601 = function(date) { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate(); }; var formatters = { mdy: this.formatAsMdy, dmy: this.formatAsDmy, ymd: this.formatAsYmd, 'ISO 8601': this.formatAsISO8601 }; /** * Formats date according to stored preference * * @param {Date} date date to format * * @return {String} formatted date as String */ this.format = function(date) { return formatters[format](date); }; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return proveit.STATIC_BASE + "page_white.png"; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "page_white_world.png", book: "book.png", journal: "page_white_text.png", news: "newspaper.png", newsgroup: "comments.png", "press release": "transmit_blue.png", interview: "telephone.png", episode: "television.png", "AV media": "film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return proveit.STATIC_BASE + icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return proveit.STATIC_BASE + 'raw.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.dateFormatter.format(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? $(paramBox).show(); paramList.appendChild(paramBox); } $genPane.show(); $(citePanes).prepend($genPane); }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div>', {id: this.GUI_ID}); var tabs = $('<div>', {id: 'tabs'}); var created = $('<h1>'); var createdLink = $('<a>').attr({title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img>').attr({src: this.STATIC_BASE + 'logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button>', {text: 'show/hide'}); created.append(showHideButton); tabs.append(created); var header = $('<ul>'); var view = $('<li>'); // View tab link var viewLink = $('<a>').attr({id: 'view-link', "class": 'tab-link', href: '#view-tab'}).text('References ('); var numRefs = $('<span>').attr({id: 'numRefs'}).text('0'); viewLink.append(numRefs, ')'); view.append(viewLink); header.append(view); var add = $('<li>'); // Add tab link var addLink = $('<a>').attr({id: 'add-link', "class": 'tab-link', href: '#add-tab'}).text('Add a Reference'); add.append(addLink); header.append(add); tabs.append(header); // View tab var viewTab = $('<div>', {id: 'view-tab', css: {display: 'none'}}); // View pane used for displaying references; within view tab var viewPane = $('<div>', {id: 'view-pane'}); var viewScroll = $('<div>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table>', {id: 'refs'}); var dummyRef = $('<tr>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td>', {"class": 'number'})). append($('<td>', {"class": 'type'})). append($('<td>', {"class": 'title'})); //append($('<td>', {"class": 'details'})); var editTd = $('<td>', {"class": 'edit'}). append($('<button>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewTab.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); // div.ref-name-row var refNameRow = $('<div>', {"class": 'ref-name-row', tabindex: -1}); var refLabel = $('<label>', {'for': 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc'}). append('&lt;ref&gt; name'); refNameRow.append(refLabel); refNameRow.append($('<input/>', {id: 'editrefname', "class": 'paramvalue', tabindex: 0})); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewTab.append(editPane); tabs.append(viewTab); // dumy cite pane var dummyCite = $('<div/>', {id: 'dummyCitePane', "class": 'typepane', style: 'display: none'}); var addRefNameRow = refNameRow.clone(); //$('input', addRefNameRow).attr('id', 'addrefname'); //$('label', addRefNameRow).attr('for', 'addrefname'); dummyCite.append(addRefNameRow); dummyCite.append($('<div/>', {"class": 'paramlist'})); tabs.append(dummyCite); var preloadedparam = $('<div/>', {id: 'preloadedparamrow', "class": 'preloadedrow input-row', style: 'display: none'}). append($('<label/>', {"class": 'paramdesc'})); var paramvalue = $('<input/>', {"class": 'paramvalue', tabindex: 0}); preloadedparam.append(paramvalue); var deleteButton = $('<button/>', {"class": 'delete-field', tabindex: -1}). append('delete field'); preloadedparam.append(deleteButton); tabs.append(preloadedparam); var addedparam = $('<div/>', {id: 'addedparamrow', "class": 'addedrow input-row', style: 'display: none'}). append($('<input/>', {"class": 'paramdesc', tabindex: 0})). append(paramvalue.clone()). append(deleteButton.clone()); tabs.append(addedparam); // Add tab var addTab = $('<div/>', {id: 'add-tab', css: {display: 'none'}}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addTab.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addTab.append(addButtons); tabs.append(addTab); gui.append(tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $("#tabs").tabs({ selected: 0, show: function(event,ui) { switch(ui.index) { case 0: // view //$('tr.selected').focus(); break; case 1: // add cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); break; // case 1: // edit // proveit.updateEditPane(); // $('tr.selected').dblclick(); //break; default: // nothing } } }); // handle clicking on tabs $(viewLink).click(function(){ if($(viewTab).is(":hidden")) proveit.toggleViewAddVisibility(); else cancelEdit(); // Edit and view are the same tab, so we handle this specially. }); $(addLink).click(function(){ if($(addTab).is(":hidden")) proveit.toggleViewAddVisibility(); }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("add-tab")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#add-tab .typepane').get(0))); $("#tabs").tabs( { selected: '#view-tab' } ); $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $("#tabs").tabs( { selected: '#view-tab' } ); }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // delete field button $(".delete-field").button({ icons: { primary: 'ui-icon-close' }, text: false }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $("#view-tab, #add-tab"); this.viewAndAddPanes = viewAndAdd; function minimize() { viewAndAdd.hide(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } function maximize() { viewAndAdd.show(); showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } // set up the minimize button showHideButton.toggle( maximize, minimize ); this.toggleViewAddVisibility = function() { showHideButton.click(); }; this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: ie3tgxaqwqznzmdevwxnx3mr432bdvl 360752 360751 2014-06-29T22:30:51Z en>Mattflaschen 0 update ProveIt to d79d9de237278918781edde72be7ed0ce2c23b55; cleanup changes will be put back in later. 360752 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Git commit d79d9de237278918781edde72be7ed0ce2c23b55 as of 2014-06-29 from https://github.com/proveit-js/proveit * Changes should be made through that GitHub project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) * * Includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James, used under * the Creative Commons Attribution 3.0 License. */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus" } }, /** * Optional preference to specify default date format for new references. * If set, it overrides the general date preference from Special:Preferences. * * @type {String} supported date format string */ dateFormatString: null, /** * Singleton used to format dates according to user preference * * @type DateFormatter */ dateFormatter: null, /** * Gets the effective preference for date format. If there is no ProveIt-specific * preference already at proveit.dateFormatString, it will determine the correct preference * from MW user preferences. Then, it will store that value to proveit.dateFormatString * * @return {String} format string to use for dates */ getDatePreference: function () { if (this.dateFormatString === null) { this.dateFormatString = mw.user.options.get('date'); } return this.dateFormatString; }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has an edit box * * @return {Boolean} true if the page has an edit box, false otherwise */ isEditPage: function() { return wgAction == 'edit' || wgAction == 'submit'; }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return (wgCanonicalNamespace == '' || wgCanonicalNamespace == 'User' || wgPageName == 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { addOnloadHook(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection']; var preference = proveit.getDatePreference(); proveit.dateFormatter = new proveit.DateFormatter(preference); mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $("div.input-row", editPane); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number',oldRichItem).text(); $('td.number',newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = new Array(); for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').bind('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc); $(paramName).attr('title',item); $(paramValue).val(params[item]); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, // TODO: Use https://gerrit.wikimedia.org/r/#/c/67166/ when merged. /** * Date-formatting class * * @param {String} format one of the format strings supported by MW core. * Currently, the supported values are 'default', 'mdy', 'dmy', 'ymd', and 'ISO 8601'. * If an unknown value is passed, it will use wgDefaultDateFormat. */ DateFormatter: function (format) { // 1-indexed (due to filler item at 0), in page content language. var monthNames = mw.config.get('wgMonthNames'); var supportedFormats = ['mdy', 'dmy', 'ymd', 'ISO 8601']; if($.inArray(format, supportedFormats) === -1) { format = mw.config.get('wgDefaultDateFormat'); } function getMonthName(date) { return monthNames[date.getMonth() + 1];; } this.formatAsMdy = function(date) { return getMonthName(date) + ' ' + date.getDate() + ', ' + date.getFullYear(); }; this.formatAsDmy = function(date) { return date.getDate() + ' ' + getMonthName(date) + ' ' + date.getFullYear(); }; this.formatAsYmd = function(date) { return date.getFullYear() + ' ' + getMonthName(date) + ' ' + date.getDate(); }; this.formatAsISO8601 = function(date) { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate(); }; var formatters = { mdy: this.formatAsMdy, dmy: this.formatAsDmy, ymd: this.formatAsYmd, 'ISO 8601': this.formatAsISO8601 }; /** * Formats date according to stored preference * * @param {Date} date date to format * * @return {String} formatted date as String */ this.format = function(date) { return formatters[format](date); }; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return '//upload.wikimedia.org/wikipedia/commons/d/dd/Silk-Page_white.png'; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "//upload.wikimedia.org/wikipedia/commons/f/f0/Silk-Page_white_world.png", book: "//upload.wikimedia.org/wikipedia/commons/1/1e/Silk-Book.png", journal: "//upload.wikimedia.org/wikipedia/commons/f/f8/Silk-Page_white_text.png", news: "//upload.wikimedia.org/wikipedia/commons/3/32/Silk-Newspaper.png", newsgroup: "//upload.wikimedia.org/wikipedia/commons/5/5c/Silk-Comments.png", "press release": "//upload.wikimedia.org/wikipedia/commons/b/bd/Silk-Transmit_blue.png", interview: "//upload.wikimedia.org/wikipedia/commons/f/f7/Silk-Telephone.png", episode: "//upload.wikimedia.org/wikipedia/commons/b/b2/Silk-Television.png", "AV media": "//upload.wikimedia.org/wikipedia/commons/1/1a/Silk-film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return 'https://upload.wikimedia.org/wikipedia/commons/d/db/Silk-Page_white_code_red.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.dateFormatter.format(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? paramList.appendChild(paramBox); } $(citePanes).prepend($genPane); }, /** * Creates and returns a hidden element holding the template elements * (placeholder elements later cloned and filled with real data) * * @return {jQuery} $root Hidden root element holding templates */ createTemplateElement: function() { var $root = $('<div>', { id: 'proveit-templates' }); // Dummy cite pane var dummyCite = $('<div>', { id: 'dummyCitePane', "class": 'typepane' }); var $addRefNameRow = this.createRefNameRow(); //$('input', $addRefNameRow).attr('id', 'addrefname'); //$('label', $addRefNameRow).attr('for', 'addrefname'); dummyCite.append($addRefNameRow); dummyCite.append($('<div>', {"class": 'paramlist'})); $root.append(dummyCite); var preloadedparam = $('<div>', { id: 'preloadedparamrow', "class": 'preloadedrow input-row' }).append($('<label>', { "class": 'paramdesc' })); var paramvalue = $('<input>', { "class": 'paramvalue', tabindex: 0 }); preloadedparam.append(paramvalue); var deleteButton = $('<button>', { "class": 'delete-field', tabindex: -1 }).text('delete field'); deleteButton.button({ icons: { primary: 'ui-icon-close' }, text: false }); preloadedparam.append(deleteButton); $root.append(preloadedparam); var addedparam = $('<div>', { id: 'addedparamrow', "class": 'addedrow input-row'}). append($('<input>', { "class": 'paramdesc', tabindex: 0 })). append(paramvalue.clone()). append(deleteButton.clone()); $root.append(addedparam); return $root; }, /** * Creates a row to be used to input name attribute of the ref (<ref name="..." />) * * @return {jQuery} <ref> name row */ createRefNameRow: function() { // div.ref-name-row var $refNameRow = $('<div>', { "class": 'ref-name-row', tabindex: -1 }); var refLabel = $('<label>', { "for": 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc' }).text('<ref> name'); $refNameRow.append(refLabel); $refNameRow.append($('<input>', { id: 'editrefname', "class": 'paramvalue', tabindex: 0 })); return $refNameRow; }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div/>', {id: this.GUI_ID}); var $tabs = $('<div/>', {id: 'proveit-tabs'}); var created = $('<h1/>'); var createdLink = $('<a/>', {title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img/>', {src: 'https://upload.wikimedia.org/wikipedia/commons/0/0d/ProveIt_user_interface_logo.png', alt: 'ProveIt', height: 30, width: 118 }); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button>', { id: 'proveit-show-hide-toggle' } ).text('show/hide'); created.append(showHideButton); $tabs.append(created); var header = $('<ul/>'); var view = $('<li/>'); // View tab link // TODO: Rename view-link, add-link, view-tab, add-tab to match jQuery UI Tabs terminology to avoid confusion. var viewTab = $('<a/>', {id: 'proveit-view-tab', "class": 'tab-link', href: '#proveit-view-edit-panel'}); viewTab.append('References ('); var numRefs = $('<span/>', {id: 'numRefs'}). append('0'); viewTab.append(numRefs). append(')'); view.append(viewTab); header.append(view); var add = $('<li/>'); // Add tab link var addTab = $('<a/>', {id: 'proveit-add-tab', "class": 'tab-link', href: '#proveit-add-panel'}). append('Add a Reference'); add.append(addTab); header.append(add); $tabs.append(header); // View and edit panel var viewEditPanel = $('<div/>', {id: 'proveit-view-edit-panel'}); // View pane used for displaying references; within view tab var viewPane = $('<div/>', {id: 'view-pane'}); var viewScroll = $('<div/>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table/>', {id: 'refs'}); var dummyRef = $('<tr/>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td/>', {"class": 'number'})). append($('<td/>', {"class": 'type'})). append($('<td/>', {"class": 'title'})); //append($('<td/>', {"class": 'details'})); var editTd = $('<td/>', {"class": 'edit'}). append($('<button/>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewEditPanel.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div/>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div/>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var refNameRow = this.createRefNameRow(); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewEditPanel.append(editPane); $tabs.append(viewEditPanel); // Add panel var addPanel = $('<div/>', {id: 'proveit-add-panel'}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addPanel.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addPanel.append(addButtons); $tabs.append(addPanel); gui.append($tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $tabs.tabs({ collapsible: true, active: false, // Initially all collapsed beforeActivate: function(event, ui) { // TODO: Select just-added item in reference list, upon moving from add tab to view tab // Is this event caused by a click on a tab? var isClickOnTab = event.currentTarget && $(event.currentTarget).is('.tab-link'); // Moving to add (including maximizing) if(ui.newPanel.is(addPanel)) { cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); } if(ui.newPanel.length === 0) { if(isClickOnTab) { // Don't allow collapsing by clicking a tab. event.preventDefault(); // Clicked view tab when either view or edit was showing if(ui.oldPanel.is(viewEditPanel)) { // Cancel the edit and show reference list cancelEdit(); } } else { // They clicked the show/hide button; let it collapse and update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } } else { // There is a visible new panel; update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } } }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("proveit-add-panel")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#proveit-add-panel .typepane').get(0))); $tabs.tabs( { active: 0 } ); // Activate view panel $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $tabs.tabs( { active: 0 } ); // Activate view panel }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $(viewEditPanel).add(addPanel); this.viewAndAddPanes = viewAndAdd; var prevActiveTabPaneIndex = 0; function minimize() { prevActiveTabPaneIndex = $tabs.tabs('option', 'active'); // Collapse all tabs $tabs.tabs('option', 'active', false); } function maximize() { $tabs.tabs('option', 'active', prevActiveTabPaneIndex); } this.toggleViewAddVisibility = function() { // All tabs collapsed if($tabs.tabs('option', 'active') === false) { maximize(); } else { minimize(); } }; showHideButton.click(this.toggleViewAddVisibility); this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); gui.append(this.createTemplateElement()); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = wgServer + '/w/index.php?title=Special%3ABookSources&isbn=' + ref.params['isbn']; break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: 065dxdhgy787nyyi0eh3mq1x3u8ezq6 360753 360752 2014-07-27T04:07:15Z en>Mattflaschen 0 update ProveIt to 195034455e9d4b34fdf4980c7cf498579f4a68a5 360753 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Git commit 195034455e9d4b34fdf4980c7cf498579f4a68a5 as of 2014-07-26 from https://github.com/proveit-js/proveit * Changes should be made through that GitHub project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) * * Includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James, used under * the Creative Commons Attribution 3.0 License. */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus" } }, /** * Optional preference to specify default date format for new references. * If set, it overrides the general date preference from Special:Preferences. * * @type {String} supported date format string */ dateFormatString: null, /** * Singleton used to format dates according to user preference * * @type DateFormatter */ dateFormatter: null, /** * Gets the effective preference for date format. If there is no ProveIt-specific * preference already at proveit.dateFormatString, it will determine the correct preference * from MW user preferences. Then, it will store that value to proveit.dateFormatString * * @return {String} format string to use for dates */ getDatePreference: function () { if (this.dateFormatString === null) { this.dateFormatString = mw.user.options.get('date'); } return this.dateFormatString; }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has a wikitext edit box * * @return {Boolean} true if the page has a wikitext edit box, false otherwise */ isEditPage: function() { var contentModel = mw.config.get( 'wgPageContentModel' ), action = mw.config.get( 'wgAction' ); return contentModel === 'wikitext' && ( action === 'edit' || action === 'submit' ); }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { var namespace = mw.config.get( 'wgCanonicalNamespace' ), pageName = mw.config.get( 'wgPageName' ); // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return ( namespace === '' || namespace === 'User' || pageName === 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getRefBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getMWEditBox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getMWEditValue(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getMWEditBox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getMWEditValue: function() { var box = this.getMWEditBox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getEditSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getEditSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getMWEditBox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { $(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection', 'mediawiki.util']; var preference = proveit.getDatePreference(); proveit.dateFormatter = new proveit.DateFormatter(preference); mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getRefBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getMWEditBox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $(editPane).find("div.input-row"); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(paramRow).find(".paramvalue")[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(paramRow).find(".paramdesc")[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeRefBoxRow(ref, true); var oldRichItem = $('.selected', this.getRefBox()).get(0); var oldNumber = $('td.number', oldRichItem).text(); $('td.number', newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = []; for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').on('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc).attr('title', item); $(paramValue).val(params[item]); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitNameVals: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForRefs: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getMWEditValue(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeRef(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeRef: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitNameVals(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, // TODO: Use https://gerrit.wikimedia.org/r/#/c/67166/ when merged. /** * Date-formatting class * * @param {String} format one of the format strings supported by MW core. * Currently, the supported values are 'default', 'mdy', 'dmy', 'ymd', and 'ISO 8601'. * If an unknown value is passed, it will use wgDefaultDateFormat. */ DateFormatter: function (format) { // 1-indexed (due to filler item at 0), in page content language. var monthNames = mw.config.get('wgMonthNames'); var supportedFormats = ['mdy', 'dmy', 'ymd', 'ISO 8601']; if($.inArray(format, supportedFormats) === -1) { format = mw.config.get('wgDefaultDateFormat'); } function getMonthName(date) { return monthNames[date.getMonth() + 1]; } this.formatAsMdy = function(date) { return getMonthName(date) + ' ' + date.getDate() + ', ' + date.getFullYear(); }; this.formatAsDmy = function(date) { return date.getDate() + ' ' + getMonthName(date) + ' ' + date.getFullYear(); }; this.formatAsYmd = function(date) { return date.getFullYear() + ' ' + getMonthName(date) + ' ' + date.getDate(); }; this.formatAsISO8601 = function(date) { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate(); }; var formatters = { mdy: this.formatAsMdy, dmy: this.formatAsDmy, ymd: this.formatAsYmd, 'ISO 8601': this.formatAsISO8601 }; /** * Formats date according to stored preference * * @param {Date} date date to format * * @return {String} formatted date as String */ this.format = function(date) { return formatters[format](date); }; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getMWEditBox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getMWEditValue(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return '//upload.wikimedia.org/wikipedia/commons/d/dd/Silk-Page_white.png'; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "//upload.wikimedia.org/wikipedia/commons/f/f0/Silk-Page_white_world.png", book: "//upload.wikimedia.org/wikipedia/commons/1/1e/Silk-Book.png", journal: "//upload.wikimedia.org/wikipedia/commons/f/f8/Silk-Page_white_text.png", news: "//upload.wikimedia.org/wikipedia/commons/3/32/Silk-Newspaper.png", newsgroup: "//upload.wikimedia.org/wikipedia/commons/5/5c/Silk-Comments.png", "press release": "//upload.wikimedia.org/wikipedia/commons/b/bd/Silk-Transmit_blue.png", interview: "//upload.wikimedia.org/wikipedia/commons/f/f7/Silk-Telephone.png", episode: "//upload.wikimedia.org/wikipedia/commons/b/b2/Silk-Television.png", "AV media": "//upload.wikimedia.org/wikipedia/commons/1/1a/Silk-film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return 'https://upload.wikimedia.org/wikipedia/commons/d/db/Silk-Page_white_code_red.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getRefFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.dateFormatter.format(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? paramList.appendChild(paramBox); } $(citePanes).prepend($genPane); }, /** * Creates and returns a hidden element holding the template elements * (placeholder elements later cloned and filled with real data) * * @return {jQuery} $root Hidden root element holding templates */ createTemplateElement: function() { var $root = $('<div>', { id: 'proveit-templates' }); // Dummy cite pane var dummyCite = $('<div>', { id: 'dummyCitePane', "class": 'typepane' }); var $addRefNameRow = this.createRefNameRow(); //$('input', $addRefNameRow).attr('id', 'addrefname'); //$('label', $addRefNameRow).attr('for', 'addrefname'); dummyCite.append($addRefNameRow); dummyCite.append($('<div>', {"class": 'paramlist'})); $root.append(dummyCite); var preloadedparam = $('<div>', { id: 'preloadedparamrow', "class": 'preloadedrow input-row' }).append($('<label>', { "class": 'paramdesc' })); var paramvalue = $('<input>', { "class": 'paramvalue', tabindex: 0 }); preloadedparam.append(paramvalue); var deleteButton = $('<button>', { "class": 'delete-field', tabindex: -1 }).text('delete field'); deleteButton.button({ icons: { primary: 'ui-icon-close' }, text: false }); preloadedparam.append(deleteButton); $root.append(preloadedparam); var addedparam = $('<div>', { id: 'addedparamrow', "class": 'addedrow input-row'}). append($('<input>', { "class": 'paramdesc', tabindex: 0 })). append(paramvalue.clone()). append(deleteButton.clone()); $root.append(addedparam); return $root; }, /** * Creates a row to be used to input name attribute of the ref (<ref name="..." />) * * @return {jQuery} <ref> name row */ createRefNameRow: function() { // div.ref-name-row var $refNameRow = $('<div>', { "class": 'ref-name-row', tabindex: -1 }); var refLabel = $('<label>', { "for": 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc' }).text('<ref> name'); $refNameRow.append(refLabel); $refNameRow.append($('<input>', { id: 'editrefname', "class": 'paramvalue', tabindex: 0 })); return $refNameRow; }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div>', {id: this.GUI_ID}); var $tabs = $('<div>', {id: 'proveit-tabs'}); var created = $('<h1>'); var createdLink = $('<a>').attr({title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img>' ).attr( {src: 'https://upload.wikimedia.org/wikipedia/commons/0/0d/ProveIt_user_interface_logo.png', alt: 'ProveIt', height: 30, width: 118 } ); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button>', { id: 'proveit-show-hide-toggle' } ).text('show/hide'); created.append(showHideButton); $tabs.append(created); var header = $('<ul>'); var view = $('<li>'); // View tab link var viewTab = $('<a/>', {id: 'proveit-view-tab', "class": 'tab-link', href: '#proveit-view-edit-panel'}).text('References ('); var numRefs = $('<span>').attr({id: 'numRefs'}).text('0'); viewTab.append(numRefs, ')'); view.append(viewTab); header.append(view); var add = $('<li>'); // Add tab link var addTab = $('<a>').attr({id: 'proveit-add-tab', "class": 'tab-link', href: '#proveit-add-panel'}).text('Add a Reference'); add.append(addTab); header.append(add); $tabs.append(header); // View and edit panel var viewEditPanel = $('<div>', {id: 'proveit-view-edit-panel'}); // View pane used for displaying references; within view tab var viewPane = $('<div>', {id: 'view-pane'}); var viewScroll = $('<div>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table>', {id: 'refs'}); var dummyRef = $('<tr>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td>', {"class": 'number'})). append($('<td>', {"class": 'type'})). append($('<td>', {"class": 'title'})); //append($('<td>', {"class": 'details'})); var editTd = $('<td>', {"class": 'edit'}). append($('<button>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewEditPanel.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var refNameRow = this.createRefNameRow(); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewEditPanel.append(editPane); $tabs.append(viewEditPanel); // Add panel var addPanel = $('<div/>', {id: 'proveit-add-panel'}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addPanel.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addPanel.append(addButtons); $tabs.append(addPanel); gui.append($tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $tabs.tabs({ collapsible: true, active: false, // Initially all collapsed beforeActivate: function(event, ui) { // TODO: Select just-added item in reference list, upon moving from add tab to view tab // Is this event caused by a click on a tab? var isClickOnTab = event.currentTarget && $(event.currentTarget).is('.tab-link'); // Moving to add (including maximizing) if(ui.newPanel.is(addPanel)) { cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); } if(ui.newPanel.length === 0) { if(isClickOnTab) { // Don't allow collapsing by clicking a tab. event.preventDefault(); // Clicked view tab when either view or edit was showing if(ui.oldPanel.is(viewEditPanel)) { // Cancel the edit and show reference list cancelEdit(); } } else { // They clicked the show/hide button; let it collapse and update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } } else { // There is a visible new panel; update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } } }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("proveit-add-panel")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getRefFromAddPane($('#proveit-add-panel .typepane').get(0))); $tabs.tabs( { active: 0 } ); // Activate view panel $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $tabs.tabs( { active: 0 } ); // Activate view panel }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $(viewEditPanel).add(addPanel); this.viewAndAddPanes = viewAndAdd; var prevActiveTabPaneIndex = 0; function minimize() { prevActiveTabPaneIndex = $tabs.tabs('option', 'active'); // Collapse all tabs $tabs.tabs('option', 'active', false); } function maximize() { $tabs.tabs('option', 'active', prevActiveTabPaneIndex); } this.toggleViewAddVisibility = function() { // All tabs collapsed if($tabs.tabs('option', 'active') === false) { maximize(); } else { minimize(); } }; showHideButton.click(this.toggleViewAddVisibility); this.scanForRefs(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); gui.append(this.createTemplateElement()); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeRefBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getRefBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = mw.util.getUrl( 'Special:BookSources', { isbn: ref.params['isbn'] } ); break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getMWEditValue(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getRefBox(); $(refbox).append(this.makeRefBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: oj5pm4nlqg0uhas62h9ncv5l9qakko2 360754 360753 2015-03-09T06:54:03Z en>Mattflaschen 0 Deploy commit 72b9abf17fe33ab8af55a7cfb074a9beb35365ab of ProveIt. 360754 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Git commit 72b9abf17fe33ab8af55a7cfb074a9beb35365ab as of 2015-03-09 from https://github.com/proveit-js/proveit * Changes should be made through that GitHub project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) * * Includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James, used under * the Creative Commons Attribution 3.0 License. */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus" } }, /** * Optional preference to specify default date format for new references. * If set, it overrides the general date preference from Special:Preferences. * * @type {String} supported date format string */ dateFormatString: null, /** * Singleton used to format dates according to user preference * * @type DateFormatter */ dateFormatter: null, /** * Gets the effective preference for date format. If there is no ProveIt-specific * preference already at proveit.dateFormatString, it will determine the correct preference * from MW user preferences. Then, it will store that value to proveit.dateFormatString * * @return {String} format string to use for dates */ getDatePreference: function () { if (this.dateFormatString === null) { this.dateFormatString = mw.user.options.get('date'); } return this.dateFormatString; }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has a wikitext edit box * * @return {Boolean} true if the page has a wikitext edit box, false otherwise */ isEditPage: function() { var contentModel = mw.config.get( 'wgPageContentModel' ), action = mw.config.get( 'wgAction' ); return contentModel === 'wikitext' && ( action === 'edit' || action === 'submit' ); }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { var namespace = mw.config.get( 'wgCanonicalNamespace' ), pageName = mw.config.get( 'wgPageName' ); // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return ( namespace === '' || namespace === 'User' || pageName === 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getReferenceBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getTextbox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getTextboxText(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getTextbox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getTextboxText: function() { var box = this.getTextbox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getTextbox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { $(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection', 'mediawiki.util']; var preference = proveit.getDatePreference(); proveit.dateFormatter = new proveit.DateFormatter(preference); mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getReferenceBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getTextbox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $(editPane).find("div.input-row"); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(paramRow).find(".paramvalue")[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(paramRow).find(".paramdesc")[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeReferenceBoxRow(ref, true); var oldRichItem = $('.selected', this.getReferenceBox()).get(0); var oldNumber = $('td.number', oldRichItem).text(); $('td.number', newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = []; for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').on('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc).attr('title', item); $(paramValue).val(params[item]); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitKeysAndValues: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForReferences: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getTextboxText(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeReference(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeReference: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitKeysAndValues(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, // TODO: Use https://gerrit.wikimedia.org/r/#/c/67166/ when merged. /** * Date-formatting class * * @param {String} format one of the format strings supported by MW core. * Currently, the supported values are 'default', 'mdy', 'dmy', 'ymd', and 'ISO 8601'. * If an unknown value is passed, it will use wgDefaultDateFormat. */ DateFormatter: function (format) { // 1-indexed (due to filler item at 0), in page content language. var monthNames = mw.config.get('wgMonthNames'); var supportedFormats = ['mdy', 'dmy', 'ymd', 'ISO 8601']; if($.inArray(format, supportedFormats) === -1) { format = mw.config.get('wgDefaultDateFormat'); } function getMonthName(date) { return monthNames[date.getMonth() + 1]; } this.formatAsMdy = function(date) { return getMonthName(date) + ' ' + date.getDate() + ', ' + date.getFullYear(); }; this.formatAsDmy = function(date) { return date.getDate() + ' ' + getMonthName(date) + ' ' + date.getFullYear(); }; this.formatAsYmd = function(date) { return date.getFullYear() + ' ' + getMonthName(date) + ' ' + date.getDate(); }; this.formatAsISO8601 = function(date) { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate(); }; var formatters = { mdy: this.formatAsMdy, dmy: this.formatAsDmy, ymd: this.formatAsYmd, 'ISO 8601': this.formatAsISO8601 }; /** * Formats date according to stored preference * * @param {Date} date date to format * * @return {String} formatted date as String */ this.format = function(date) { return formatters[format](date); }; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getTextbox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getTextboxText(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return '//upload.wikimedia.org/wikipedia/commons/d/dd/Silk-Page_white.png'; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi", "pmid" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "//upload.wikimedia.org/wikipedia/commons/f/f0/Silk-Page_white_world.png", book: "//upload.wikimedia.org/wikipedia/commons/1/1e/Silk-Book.png", journal: "//upload.wikimedia.org/wikipedia/commons/f/f8/Silk-Page_white_text.png", news: "//upload.wikimedia.org/wikipedia/commons/3/32/Silk-Newspaper.png", newsgroup: "//upload.wikimedia.org/wikipedia/commons/5/5c/Silk-Comments.png", "press release": "//upload.wikimedia.org/wikipedia/commons/b/bd/Silk-Transmit_blue.png", interview: "//upload.wikimedia.org/wikipedia/commons/f/f7/Silk-Telephone.png", episode: "//upload.wikimedia.org/wikipedia/commons/b/b2/Silk-Television.png", "AV media": "//upload.wikimedia.org/wikipedia/commons/1/1a/Silk-film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return 'https://upload.wikimedia.org/wikipedia/commons/d/db/Silk-Page_white_code_red.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getReferenceFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.dateFormatter.format(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? paramList.appendChild(paramBox); } $(citePanes).prepend($genPane); }, /** * Creates and returns a hidden element holding the template elements * (placeholder elements later cloned and filled with real data) * * @return {jQuery} $root Hidden root element holding templates */ createTemplateElement: function() { var $root = $('<div>', { id: 'proveit-templates' }); // Dummy cite pane var dummyCite = $('<div>', { id: 'dummyCitePane', "class": 'typepane' }); var $addRefNameRow = this.createReferenceNameRow(); //$('input', $addRefNameRow).attr('id', 'addrefname'); //$('label', $addRefNameRow).attr('for', 'addrefname'); dummyCite.append($addRefNameRow); dummyCite.append($('<div>', {"class": 'paramlist'})); $root.append(dummyCite); var preloadedparam = $('<div>', { id: 'preloadedparamrow', "class": 'preloadedrow input-row' }).append($('<label>', { "class": 'paramdesc' })); var paramvalue = $('<input>', { "class": 'paramvalue', tabindex: 0 }); preloadedparam.append(paramvalue); var deleteButton = $('<button>', { "class": 'delete-field', tabindex: -1 }).text('delete field'); deleteButton.button({ icons: { primary: 'ui-icon-close' }, text: false }); preloadedparam.append(deleteButton); $root.append(preloadedparam); var addedparam = $('<div>', { id: 'addedparamrow', "class": 'addedrow input-row'}). append($('<input>', { "class": 'paramdesc', tabindex: 0 })). append(paramvalue.clone()). append(deleteButton.clone()); $root.append(addedparam); return $root; }, /** * Creates a row to be used to input name attribute of the ref (<ref name="..." />) * * @return {jQuery} <ref> name row */ createReferenceNameRow: function() { // div.ref-name-row var $refNameRow = $('<div>', { "class": 'ref-name-row', tabindex: -1 }); var refLabel = $('<label>', { "for": 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc' }).text('<ref> name'); $refNameRow.append(refLabel); $refNameRow.append($('<input>', { id: 'editrefname', "class": 'paramvalue', tabindex: 0 })); return $refNameRow; }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div>', {id: this.GUI_ID}); var $tabs = $('<div>', {id: 'proveit-tabs'}); var created = $('<h1>'); var createdLink = $('<a>').attr({title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img>' ).attr( {src: 'https://upload.wikimedia.org/wikipedia/commons/0/0d/ProveIt_user_interface_logo.png', alt: 'ProveIt', height: 30, width: 118 } ); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button>', { id: 'proveit-show-hide-toggle' } ).text('show/hide'); created.append(showHideButton); $tabs.append(created); var header = $('<ul>'); var view = $('<li>'); // View tab link var viewTab = $('<a/>', {id: 'proveit-view-tab', "class": 'tab-link', href: '#proveit-view-edit-panel'}).text('References ('); var numRefs = $('<span>').attr({id: 'numRefs'}).text('0'); viewTab.append(numRefs, ')'); view.append(viewTab); header.append(view); var add = $('<li>'); // Add tab link var addTab = $('<a>').attr({id: 'proveit-add-tab', "class": 'tab-link', href: '#proveit-add-panel'}).text('Add a Reference'); add.append(addTab); header.append(add); $tabs.append(header); // View and edit panel var viewEditPanel = $('<div>', {id: 'proveit-view-edit-panel'}); // View pane used for displaying references; within view tab var viewPane = $('<div>', {id: 'view-pane'}); var viewScroll = $('<div>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table>', {id: 'refs'}); var dummyRef = $('<tr>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td>', {"class": 'number'})). append($('<td>', {"class": 'type'})). append($('<td>', {"class": 'title'})); //append($('<td>', {"class": 'details'})); var editTd = $('<td>', {"class": 'edit'}). append($('<button>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewEditPanel.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var refNameRow = this.createReferenceNameRow(); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewEditPanel.append(editPane); $tabs.append(viewEditPanel); // Add panel var addPanel = $('<div/>', {id: 'proveit-add-panel'}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addPanel.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addPanel.append(addButtons); $tabs.append(addPanel); gui.append($tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $tabs.tabs({ collapsible: true, active: false, // Initially all collapsed beforeActivate: function(event, ui) { // TODO: Select just-added item in reference list, upon moving from add tab to view tab // Is this event caused by a click on a tab? var isClickOnTab = event.currentTarget && $(event.currentTarget).is('.tab-link'); // Moving to add (including maximizing) if(ui.newPanel.is(addPanel)) { cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); } if(ui.newPanel.length === 0) { if(isClickOnTab) { // Don't allow collapsing by clicking a tab. event.preventDefault(); // Clicked view tab when either view or edit was showing if(ui.oldPanel.is(viewEditPanel)) { // Cancel the edit and show reference list cancelEdit(); } } else { // They clicked the show/hide button; let it collapse and update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } } else { // There is a visible new panel; update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } } }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("proveit-add-panel")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getReferenceFromAddPane($('#proveit-add-panel .typepane').get(0))); $tabs.tabs( { active: 0 } ); // Activate view panel $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $tabs.tabs( { active: 0 } ); // Activate view panel }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $(viewEditPanel).add(addPanel); this.viewAndAddPanes = viewAndAdd; var prevActiveTabPaneIndex = 0; function minimize() { prevActiveTabPaneIndex = $tabs.tabs('option', 'active'); // Collapse all tabs $tabs.tabs('option', 'active', false); } function maximize() { $tabs.tabs('option', 'active', prevActiveTabPaneIndex); } this.toggleViewAddVisibility = function() { // All tabs collapsed if($tabs.tabs('option', 'active') === false) { maximize(); } else { minimize(); } }; showHideButton.click(this.toggleViewAddVisibility); this.scanForReferences(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); gui.append(this.createTemplateElement()); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeReferenceBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getReferenceBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = mw.util.getUrl( 'Special:BookSources', { isbn: ref.params['isbn'] } ); break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getTextboxText(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getReferenceBox(); $(refbox).append(this.makeReferenceBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: hnr0117q2elln4cdploj302nqdduy42 360755 360754 2016-08-09T13:27:35Z en>Sophivorus 0 The code of the latest version is now served from Commons 360755 javascript text/javascript /** * ProveIt is a gadget that adds a graphical user interface to find, edit, add and cite references. * The code of the gadget is loaded directly from Wikimedia Commons. * The full documentation can be found at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt */ mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&action=raw&ctype=text/javascript' ); mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&action=raw&ctype=text/css', 'text/css' ); 9bebuawtd6perisk1ad1rzeg6qn5ota 360756 360755 2016-08-11T15:46:30Z en>Sophivorus 0 360756 javascript text/javascript mw.loader.load( '//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&oldid=650571979&action=raw&ctype=text/javascript' ); mw.loader.load( '//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&oldid=650571981&action=raw&ctype=text/css', 'text/css' ); gfjht5ophvztwrl6ptu9jsxfh57f4p5 360757 360756 2016-08-15T18:09:41Z en>Sophivorus 0 Revert to previous version 360757 javascript text/javascript /* _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. | * |_____________________________________________________________________________| */ /* * Imported from Git commit 72b9abf17fe33ab8af55a7cfb074a9beb35365ab as of 2015-03-09 from https://github.com/proveit-js/proveit * Changes should be made through that GitHub project. */ /* * ProveIt ([[User:ProveIt GT]]) is a powerful GUI tool for viewing, adding, editing, and inserting references on Wikipedia. * * Copyright 2008 - 2011 * * Georgia Tech Research Corporation * * Atlanta, GA 30332-0415 * * Copyright 2011 - * * Matthew Flaschen * * ALL RIGHTS RESERVED * * ProveIt is available under the GNU Free Documentation License (GFDL-1.3.txt), Creative Commons * Attribution/Share-Alike License 3.0 (http://creativecommons.org/licenses/by-sa/3.0/), and the GNU * General Public License 2 (GPL-2.txt) * * Includes icons from the Silk set (http://www.famfamfam.com/lab/icons/silk/), by Mark James, used under * the Creative Commons Attribution 3.0 License. */ /** * Electronic Learning Communities * @module elc */ ( function ( mw, $ ) { /* Second parameter (pre-existing proveit object, if any) passed to extend overrides first. Gives users option to easily override initial constants, such as shouldAddSummary. If proveit is unintentionally imported more than once, the first import will take precedence. */ /** * Main class and namespace for ProveIt software. This is the only global variable. * @class proveit */ var proveit = window.proveit = $.extend({ /** * Approximately half the height of the edit box. Used in scrolling when highlighting text. * @type Number */ HALF_EDIT_BOX_HEIGHT: 200, // This could be preference-controlled, instead of hard-coded. /** * Language used for descriptions * @type String */ LANG: "en", /** * Text before param name (e.g. url, title, etc.) in creation box, to avoid collisions with unrelated ids. * @type String */ NEW_PARAM_PREFIX: "newparam", /** * Text before param name (e.g. url, title, etc.) in edit box, to avoid collisions with unrelated ids. * @type String */ EDIT_PARAM_PREFIX: "editparam", GUI_ID: "proveit", /* Used to map between keys, including citation parameter names, and human-readable text. It can be * internationalized easily. Add descriptions.xx , where xx is * the ISO 639-1 code for a language, then set proveit.LANG to "xx" * to use the new descriptions. */ descriptions : { en : { agency: "Agency", name: "Name", author: "Author (L, F)", author2: "Author two (L, F)", author3: "Author three (L, F)", author4: "Author four (L, F)", author5: "Author five (L, F)", author6: "Author six (L, F)", author7: "Author seven (L, F)", author8: "Author eight (L, F)", author9: "Author nine (L, F)", last: "Last name", last2: "Last name (auth. two)", last3: "Last name (auth. three)", last4: "Last name (auth. four)", last5: "Last name (auth. five)", last6: "Last name (auth. six)", last7: "Last name (auth. seven)", last8: "Last name (auth. eight)", last9: "Last name (auth. nine)", first: "First name", first2: "First name (auth. two)", first3: "First name (auth. three)", first4: "First name (auth. four)", first5: "First name (auth. five)", first6: "First name (auth. six)", first7: "First name (auth. seven)", first8: "First name (auth. eight)", first9: "First name (auth. nine)", authorlink: "Author article name", title: "Title", trans_title: "Title in English", publisher: "Publisher", year: "Year", location: "Location", place: "Location of work", isbn: "ISBN", id: "ID", doi: "DOI", page: "Page", pages: "Pages", quote: "Quote", month: "Month", journal: "Journal", edition: "Edition", volume: "Volume", issue: "Issue", url: "URL", date: "Publication date", accessdate: "Access date", coauthors: "Co-authors", booktitle: "Title of Proceedings", contribution: "Contribution/Chapter", encyclopedia: "Encyclopedia", newsgroup: "Newsgroup", version: "Version", site: "Site", newspaper: "Newspaper", "publication-place": "Publication location", editor: "Editor (L, F)", article: "Article", pubplace: "Publisher location", pubyear: "Publication year", inventor: "Inventor (L, F)", "issue-date": "Issue date", "patent-number": "Patent number", "country-code": "Country code (XX)", work: "Work", format: "Format", issn: "ISSN", pmid: "PMID", chapter: "Chapter", web: "Web", book: "Book", conference: "Conference", news: "News", paper: "Paper", "press release": "Press release", interview: "Interview", "AV media": "Audiovisual work", subject: "Subject", subjectlink: "Subject article name", subject2: "Subject two", subjectlink2: "Subject two article name", subject3: "Subject three", subjectlink3: "Subject three article name", subject4: "Subject four", interviewer: "Interviewer", cointerviewers: "Co-interviewers", type: "Type", program: "Program", callsign: "Call sign", city: "City", archiveurl: "Archive URL", archivedate: "Date archived", episode: "Episode", episodelink: "Episode article name", series: "Series", serieslink: "Series article name", credits: "Credits", network: "Network", station: "Station", airdate: "Airdate", began: "Start date", ended: "End date", season: "Season number", seriesno: "Season number", number: "Number", minutes: "Minutes", transcript: "Transcript", transcripturl: "Transcript URL", people: "People", medium: "Production medium", language: "Language", time: "Time", oclc: "OCLC", ref: "Anchor ID", deadurl: 'Dead URL?', raw: 'Unknown format' }, // Finnish translation by Olli (ollinpostit at gmail.com) fi: { agency: "Edustaja", name: "Nimi", author: "Tekijä", author2: "Tekijä kaksi", author3: "Tekijä kolme", author4: "Tekijä neljä", author5: "Tekijä viisi", author6: "Tekijä kuusi", author7: "Tekijä seitsemän", author8: "Tekijä kahdeksan", author9: "Tekijä yhdeksän", last: "Sukunimi", last2: "Sukunimi (tekijä 2)", last3: "Sukunimi (tekijä 3)", last4: "Sukunimi (tekijä 4)", last5: "Sukunimi (tekijä 5)", last6: "Sukunimi (tekijä 6)", last7: "Sukunimi (tekijä 7)", last8: "Sukunimi (tekijä 8)", last9: "Sukunimi (tekijä 9)", first: "Etunimi", first2: "Etunimi (tekijä 2)", first3: "Etunimi (tekijä 3)", first4: "Etunimi (tekijä 4)", first5: "Etunimi (tekijä 5)", first6: "Etunimi (tekijä 6)", first7: "Etunimi (tekijä 7)", first8: "Etunimi (tekijä 8)", first9: "Etunimi (tekijä 9)", authorlink: "Tekijästä kertova sivu", title: "Otsikko", publisher: "Julkaisija", year: "Vuosi", location: "Paikka", place: "Työn paikka", isbn: "ISBN", id: "ID", doi: "DOI", page: "Sivu", pages: "Sivuja", quote: "Lainaus", month: "Kuukausi", journal: "Aikakauslehti", edition: "Painos", volume: "Vuosikerta", issue: "Numero", url: "Osoite", date: "Julkaisupäivä", accessdate: "Luettu", coauthors: "Muut tekijät", booktitle: "Jatko-osien otsikko", contribution: "Osallistuminen/yhteistyö", encyclopedia: "Tietosanakirja", newsgroup: "Uutisryhmä", version: "Versio", site: "Sivusto", newspaper: "Sanomalehti", "publication-place": "Julkaisupaikka", editor: "Toimittaja", article: "Artikkeli", pubplace: "Julkaisijan paikka", pubyear: "Julkaisuvuosi", inventor: "Keksijä", "issue-date": "Saatavilla päivänä", "patent-number": "Patenttinumero", "country-code": "Maakoodi (XX)", work: "Työ", format: "Muoto", issn: "ISSN", pmid: "PMID", chapter: "Luku", web: "Verkko", book: "Kirja", conference: "Kokous", news: "Uutiset", paper: "Lehti", "press release": "Lehdistötiedote", interview: "Haastattelu", subject: "Otsikko", subjectlink: "Artikkelin otsikko", subject2: "Otsikko kaksi", subjectlink2: "Artikkelin kaksi otsikko", subject3: "Otsikko kolme", subjectlink3: "Artikkelin kolme otsikko", subject4: "Otsikko neljä", interviewer: "Haastattelija", cointerviewers: "Muut haastattelijat", type: "Tyyppi", program: "Ohjelma", callsign: "Call sign", city: "Kaupunki", archiveurl: "Arkiston osoite", archivedate: "Arkistointipäivämäärä", episode: "Jakso", episodelink: "Jakson sivun nimi", series: "Sarja", serieslink: "Sarjan sivun nimi", credits: "Tekijät", network: "Verkko", station: "Asema", airdate: "Lähetyspäivä", began: "Aloituspäivä", ended: "Lopetuspäivä", season: "Kauden numero", seriesno: "Kauden numero", number: "Numero", minutes: "Minuutit", transcript: "Puhtaaksi kirjoitettu teksti", transcripturl: "Puhtaaksikirjoitetun osoite", video: "Video", people: "Ihmiset", medium: "Tuotantomedia", language: "Kieli", time: "Aika", oclc: "OCLC", ref: "Ankkurin ID-tunnus" } }, /** * Optional preference to specify default date format for new references. * If set, it overrides the general date preference from Special:Preferences. * * @type {String} supported date format string */ dateFormatString: null, /** * Singleton used to format dates according to user preference * * @type DateFormatter */ dateFormatter: null, /** * Gets the effective preference for date format. If there is no ProveIt-specific * preference already at proveit.dateFormatString, it will determine the correct preference * from MW user preferences. Then, it will store that value to proveit.dateFormatString * * @return {String} format string to use for dates */ getDatePreference: function () { if (this.dateFormatString === null) { this.dateFormatString = mw.user.options.get('date'); } return this.dateFormatString; }, /** * Returns descriptions for the current language. * @return {Object} descriptions */ getDescriptions: function() { //this could be made Cite-specific if needed. return this.descriptions[proveit.LANG]; }, /** * String added to logs for easy search * @type String */ LOG_MARKER: "[ProveIt] ", /** * Convenience log function * @param {...Object} var_args objects (including strings) to log */ log: function() { var args = Array.prototype.slice.call(arguments); args.unshift(this.LOG_MARKER); mw.log.apply(mw, args); }, /** * Log error object if possible, using error (preferable), or log, if available. * @param {Error} ex error object */ logException: function(ex) { var args = [ex, ex.stack]; if(typeof(console) === "object" && $.isFunction(console.error)) { args.unshift(this.LOG_MARKER); console.error.apply(null, args); } else { this.log.apply(this, args); } }, /** * Returns true if the page has a wikitext edit box * * @return {Boolean} true if the page has a wikitext edit box, false otherwise */ isEditPage: function() { var contentModel = mw.config.get( 'wgPageContentModel' ), action = mw.config.get( 'wgAction' ); return contentModel === 'wikitext' && ( action === 'edit' || action === 'submit' ); }, /** * Returns true if the page is likely to contain references * @return {Boolean} true if page is supported, false otherwise */ isSupportedPage: function() { var namespace = mw.config.get( 'wgCanonicalNamespace' ), pageName = mw.config.get( 'wgPageName' ); // "Regular" article, userspace, or Wikipedia:Sandbox (exception for testing). return ( namespace === '' || namespace === 'User' || pageName === 'Wikipedia:Sandbox'); }, /** * Convenience function. Returns the refbox element. * @return {$Node} reference box */ getReferenceBox: function() { return $("#refs"); }, /** * Provides the x (left) and y (top) offsets to a given element. From QuirksMode (http://www.quirksmode.org/js/findpos.html), a freely available site by Peter-Paul Koch * @param {Node} node any HTML node * @return {Object} offsets to node, as object with left and top properties. */ getPosition: function(node) { var left = 0, top = 0; do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); return {"left": left, "top": top}; }, /** * Highlights a given length of text, at a particular index. * @param {Number} startInd start index in Wikipedia edit box * @param {Number} length length of string to highlight * @return {Boolean} always true */ highlightLengthAtIndex: function(startInd, length) { if(startInd < 0 || length < 0) { this.log("highlightStringAtIndex: invalid negative arguments"); } var box = this.getTextbox(); var origText = box.value; var editTop = this.getPosition(box).top; box.value = origText.substring(0, startInd); box.focus(); box.scrollTop = 1000000; //Larger than any real textarea (hopefully) var curScrollTop = box.scrollTop; box.value += origText.substring(startInd); if(curScrollTop > 0) { box.scrollTop = curScrollTop + this.HALF_EDIT_BOX_HEIGHT; } $(box).focus().textSelection('setSelection', { start: startInd, end: startInd + length }); editTop = this.getPosition(box).top; window.scroll(0, editTop); return true; }, /** * Highlights the first instance of a given string in the MediaWiki edit box. * @param {String} targetStr the string in the edit box to highlight * @return {Boolean} true if successful, false otherwise */ highlightTargetString: function(targetStr) { var origText = this.getTextboxText(); var startInd = origText.indexOf(targetStr); if(startInd == -1) { this.log("Target string \"" + targetStr + "\" not found."); return false; } return this.highlightLengthAtIndex(startInd, targetStr.length); }, /** * Convenience function. Returns the raw MediaWiki textarea element. * @return {Node} the edit box element */ getTextbox: function() { return $("#wpTextbox1")[0]; }, /** * Provides value of edit box with CR normalization * * @return {String} value of edit box with CRs stripped if document.selection exists */ getTextboxText: function() { var box = this.getTextbox(); var value = box.value; if(!box.selectionStart && document.selection) // IE 8-like behavior { value = value.replace(/\r\n/g, "\n"); } return value; }, /** * Returns raw edit form element, which contains MWEditBox, among other things. * @return {Node} the edit form element */ getMWEditForm: function() { return $("#editform")[0]; }, /** * Runs a given function on submission of edit form * @param {Function} subFunc function to run on submission */ addOnsubmit: function(subFunc) { var form = this.getMWEditForm(); if(!form) { throw new Error("No edit form, possibly due to protected page."); } form.addEventListener("submit", subFunc, false); }, /** * Returns the raw MW edit summary element * @return {Node} the edit summary element */ getSummary: function() { return $("#wpSummary")[0]; }, /** * Keep track of whether we have already added an onsubmit function to include ProveIt in the summary. * This guarantees the function will not be run twice. * @type Boolean */ summaryFunctionAdded: false, /** * Does the user want us to ever add "Edited by ProveIt" summary? * @type Boolean */ shouldAddSummary: true, /** * ProveIt should be visible on load (rather than requiring toolbar button click) on supported edit pages * @type Boolean */ loadVisible: true, /** * Maximize ProveIt when it first becomes visible. If false, it will start minimized. This has no effect on when it becomes visible. * @type Boolean */ loadMaximized: false, /** * Specifies to include ProveIt edit summary on next save. * Can be disabled by modifying shouldAddSummary */ includeProveItEditSummary: function() { if(this.shouldAddSummary && !this.summaryFunctionAdded) { try { var thisproveit = this; this.addOnsubmit(function() { var summary = thisproveit.getSummary(); if(summary.value.indexOf("ProveIt") == -1) { summary.value += " (edited with [[User:ProveIt_GT|ProveIt]])"; } }); this.summaryFunctionAdded = true; } catch(e) { this.log("Failed to add onsubmit handler. e.message: " + e.message); } } }, /** * Setup button so users can load ProveIt on demand */ setupButton: function() { var $box = $(this.getTextbox()); // Ensures wikiEditor is loaded $box.bind('wikiEditor-toolbar-buildSection-main', function(event, section) { delete section.groups.insert.tools.reference; section.groups.insert.tools.proveit = { label: 'ProveIt', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/1/19/ProveIt_logo_for_user_boxes.svg/22px-ProveIt_logo_for_user_boxes.svg.png', action: { type: 'callback', execute: function() { proveit.toggleVisibility(); } } }; }); }, /** * Sets up ProveIt if we're on an edit page. This includes setting up the toolbar button. Depending on configuration and the current page, it may also call load to show ProveIt. */ setup: function() { if(this.isEditPage()) { if(this.loadVisible && this.isSupportedPage()) { this.load(); } this.setupButton(); } }, /** * Loads dependencies and creates GUI */ load: function() { $(function() { var dependencies = ['jquery.ui.tabs', 'jquery.ui.button', 'jquery.effects.highlight', 'jquery.textSelection', 'mediawiki.util']; var preference = proveit.getDatePreference(); proveit.dateFormatter = new proveit.DateFormatter(preference); mw.loader.using(dependencies, function() { try { proveit.createGUI(); if(proveit.loadMaximized) { proveit.toggleViewAddVisibility(); } } catch(ex) { proveit.logException(ex); } }, function(ex, errorDependencies) { proveit.log('Failed to load one of: ', errorDependencies); }); }); }, /** * Clears the refBox of refBoxRows, except for dummy rows. * @return {Boolean} false if refBox wasn't found */ clearRefBox: function() { var box = this.getReferenceBox(); if(box == null) { this.log("Ref box is not loaded yet."); return false; } $("tr:not('tr#dummyRef')", box).remove(); return true; }, /** Inserts ref text into MW edit box. * @param {String} ref Reference text to insert * @param {Boolean} full Insert the full reference text if true, citation otherwise. * @return {Boolean} false if errors */ insertRefIntoMWEditBox: function(ref, full) { var txtarea = this.getTextbox(); if(!txtarea) { this.log("insertRefIntoMWEditBox: txtarea is null"); return false; } txtarea = $(txtarea); var insertionText = ref.getInsertionText(full); // Replace existing selection (if any), then scroll txtarea.textSelection('encapsulateSelection', { peri: insertionText, replace: true }); var caretPos = txtarea.textSelection('getCaretPosition', {startAndEnd: true}); // This is slightly redundant. It is called primarily for the scrollig workaround this.highlightLengthAtIndex(caretPos[0], caretPos[1] - caretPos[0]); this.includeProveItEditSummary(); }, /** * Modifies reference object from user-edited GUI. The reference object is mutated in place, so the return value is only for convenience. * * @param {Node} editPane the raw element of the editPane * @param {AbstractReference} ref the original citation object we're modifying * * @return {AbstractReference} same ref that was passed in */ changeRefFromEditPane: function(ref, editPane) { var paramBoxes = $(editPane).find("div.input-row"); var refName = $('#editrefname').val(); ref.name = refName != "" ? refName : null; // Save blank names as null // Clear old params ref.params = {}; var paramName, paramVal; for (var i = 0; i < paramBoxes.length; i++) { var paramRow = paramBoxes[i]; var valueTextbox = $(paramRow).find(".paramvalue")[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(paramRow).find(".paramdesc")[0].value); } else { paramName = valueTextbox.id.substring(this.EDIT_PARAM_PREFIX.length); } this.log("paramName: " + paramName); paramVal = $.trim(valueTextbox.value); this.log("paramVal: " + paramVal); if (paramName != "" && paramVal != "") { ref.params[paramName] = paramVal; } } if (ref.toString() != ref.orig) { ref.save = false; } ref.update(); return ref; }, /** * Creates refBoxRow, updates numbering for all refBoxRows, replaces old refBoxRow with new one, and updates ref text in MWEditBox. * @param {AbstractReference} ref the ref we want to save. */ saveRefFromEdit: function(ref) { if(!ref.save) { var newRichItem = this.makeReferenceBoxRow(ref, true); var oldRichItem = $('.selected', this.getReferenceBox()).get(0); var oldNumber = $('td.number', oldRichItem).text(); $('td.number', newRichItem).text(oldNumber); // preserve old numbering oldRichItem.parentNode.replaceChild(newRichItem, oldRichItem); $(newRichItem).addClass('selected'); ref.updateInText(); this.includeProveItEditSummary(); } }, /** * Updates the edit pane when you choose a reference to edit. * @param {AbstractReference} ref the ref that was chosen. */ updateEditPane: function(ref) { $('#editrefname').val(ref.name || ""); // Don't contaminate actual object with junk params. var tempParams = {}; for(var param in ref.params) { tempParams[param] = ref.params[param]; } // Add default params with blank values. var defaults = ref.getDefaultParams(); for(var i = 0; i < defaults.length; i++) { if(!tempParams[defaults[i]]) { tempParams[defaults[i]] = ""; } } var required = ref.getRequiredParams(); var paramNames = []; for(var item in tempParams) //First run through just to get names. { paramNames.push(item); } var sorter = ref.getSorter(); if(sorter) { paramNames.sort(sorter); } else { paramNames.sort(); } /* Sort them to provide consistent interface. Uses custom sort order (which is easily tweaked) where possible. Javascript does destructive sorting, which in this case, is convenient... */ $('#edit-fields').children('.paramlist').children().remove('div:not(.hidden)'); // clear all fields in the edit box (except the hidden ones) for(var j = 0; j < paramNames.length; j++) { this.addPaneRow($("#edit-pane").get(), tempParams, this.getDescriptions(), paramNames[j], required[paramNames[j]], true); } var acceptButton = $('#edit-buttons .accept'); var acceptEdit = function() { proveit.changeRefFromEditPane(ref, $("#edit-pane").get()); proveit.saveRefFromEdit(ref); $("#edit-pane").hide(); $("#view-pane").show(); }; // Without setTimeout, scoll reset doesn't work in Firefox. setTimeout(function() { // Reset scroll $('#edit-fields').scrollTop(0); }, 0); acceptButton.unbind('click.proveit').on('click.proveit', acceptEdit); }, /** * Add a row to an editPane or addPane. * @param {Node} root root element for pane * @param {Object} params the param object from the reference, or null for added rows. * @param {Object} descs description object to use, or null for no description * @param {String} item the current param name * @param {Boolean} req true if current param name is required, otherwise not required. * @param {Boolean} fieldType true for label, false for textbox. */ addPaneRow: function(root, params, descs, item, req, fieldType) { var id = fieldType ? "preloadedparamrow" : "addedparamrow"; var newline = $('#'+id).clone(); // clone the hidden row $(newline).attr('id',''); // clear the ID (can't have two elements with same ID) //this.activateRemoveField(newline); var paramName = $('.paramdesc', newline).eq(0); var paramValue = $('.paramvalue', newline).eq(0); $('.paramlist', root).append(newline); if(req) // if field is required... { $(paramName).addClass('required'); // visual indicator that label is required $('.delete-field', newline).remove(); // don't let people remove required fields } else { this.activateRemoveField(newline); } if(fieldType) // the description/name is a label (not a textbox) { paramName.attr("for", this.EDIT_PARAM_PREFIX + item); paramValue.attr('id',this.EDIT_PARAM_PREFIX + item); var desc = descs[item]; if(!desc) { this.log("Undefined description for param: " + item + ". Using directly as description."); desc = item; } $(paramName).text(desc).attr('title', item); $(paramValue).val(params[item]); } else { // added a new row, so make it fancy $(newline).show('highlight',{},'slow'); $('.inputs', root).scrollTop(100000); } }, /* * these are the current style and insert values to denote which one is * currently active */ /** * true signifies cite-style references, citation-style otherwise. Used when creating a reference. * @type Boolean */ togglestyle: true, // TODO: This should be eliminated if only name only inserts are allowed. /** true signifies full references, name-only otherwise. Used when inserting. * Note that new references are always inserted in full. * * @type Boolean */ toggleinsert: false, /* Cross-Browser Split 1.0.1 (c) Steven Levithan <stevenlevithan.com>; MIT License http://blog.stevenlevithan.com/archives/cross-browser-split An ECMA-compliant, uniform cross-browser split method */ /** * Cross-browser implementation of ECMAScript String.prototype.split function. * * @param {String} str input string to split * @param separator separator to split on, as RegExp or String * @param {Number} limit limit on number of splits. If the parameter is absent, no limit is imposed. * @return {Array} array resulting from split */ split: function (str, separator, limit) { // if `separator` is not a regex, use the native `split` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return proveit.split._nativeSplit.call(str, separator, limit); } var output = [], lastLastIndex = 0, flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.sticky ? "y" : ""), separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; str = str + ""; // type conversion if (!proveit.split._compliantExecNpcg) { separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt } /* behavior for `limit`: if it's... - `undefined`: no limit. - `NaN` or zero: return an empty array. - a positive number: use `Math.floor(limit)`. - a negative number: no limit. - other: type-convert, then use the above rules. */ if (limit === undefined || +limit < 0) { limit = Infinity; } else { limit = Math.floor(+limit); if (!limit) { return []; } } while (match = separator.exec(str)) { lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups if (!proveit.split._compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }, // TODO: Remove the split code, and just use a regular regex (with two main groups for name and val), iteratively. Regex.find? Make name and val indices match, and rework calling code as needed. Also, check how this was done in the original code. /** * Overly clever regex to parse template string (e.g. |last=Smith|first=John|title=My Life Story) into name and value pairs. * * names is an array of all names, and values is an array of all values. They have equal lengths. * * @param {String} workingString template string to parse. * @return {Object} object with two properties, names and values. */ splitKeysAndValues: function (workingString) { var split = {}; // The first component is "ordinary" text (no pipes), while the second is a correctly balanced wikilink, with optional pipe. Any combination of the two can appear. split.names = proveit.split(workingString.substring(workingString.indexOf("|") + 1), /=(?:[^|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/); split.names.length--; // Remove single empty element at end split.values = proveit.split(workingString.substring(workingString.indexOf("=") + 1, workingString.indexOf("}}")), /\|[^|=]*=/); return split; }, /** * Scan for references in the MWEditBox, and create a reference object and refBoxRow for each. */ scanForReferences: function() { // these are strings used to allow the correct parsing of the ref var workingstring; var cutupstring; this.clearRefBox(); var textValue = this.getTextboxText(); // since we should pick the name out before we get to the reference type, here's a variable to hold it var name; // key - name // value - // object - key - "reference", value - reference obj . Avoids repeating same object in references array. // key - "strings", value - array of orig strings var citations = {}; // Array of reference objects. At end of function, addNewElement called on each. var references = []; // allRefs should count opening refs, but not ref citation (not <ref name="..."" />) var allRefs = textValue.match(/<[\s]*ref[^\/>]*>/gi); // currentScan holds the parsed (match objects) list of references. Regex matches full or name-only reference. var currentScan = textValue.match(/<[\s]*ref[^>]*>(?:[^<]*<[\s]*\/[\s]*ref[\s]*>)?/gi); // [^<]* doesn't handle embedded HTML tags (or comments) correctly. // if there are results, if (currentScan) { for (var i = 0; i < currentScan.length; i++) { var reference = this.makeReference(currentScan[i]); if(reference) // Full reference object { name = reference.name; if(!name) // with no name, no possibility of repeat name. { references.push(reference); } } else // Not full reference. Possibly citation. { var match = currentScan[i].match(this.REF_REGEX); name = match && (match[1] || match[2] || match[3]); } if(name) { if(!citations[name]) { // Create array of original reference strings citations[name] = {}; if(!citations[name].strings) { citations[name].strings = []; } } if(reference && !citations[name].reference) // reference, and not already one for this name { citations[name].reference = reference; references.push(reference); } // Add to array citations[name].strings.push(currentScan[i]); } } } for(var j = 0; j < references.length; j++) { if(references[j].name) { var citation = citations[references[j].name]; references[j].setCitationStrings(citation.strings); } this.addNewElement(references[j]); } }, /** * Regex for parsing any reference text. * @type RegExp */ REF_REGEX: /<[\s]*ref[\s]*name[\s]*=[\s]*(?:(?:\"(.*?)\")|(?:\'(.*?)\')|(?:(.*?)))[\s]*\/?[\s]*>/, /** * Factory function for references. Takes text of a reference, and returns instance of the appropriate class. * @param {String} refText reference string * @return {AbstractReference} null if refText isn't a ref, otherwise the reference object */ makeReference: function(refText) { var isReference = /<[\s]*ref[^>]*>[^<]*\S[^<]*<[\s]*\/[\s]*ref[\s]*>/.test(refText); // Tests for reference (non-citation); if(!isReference) { return null; } var citeFunction = refText.match(/{{[\s]*cite/i) ? this.CiteReference : refText.match(/{{[\s]*Citation/i) ? this.CitationReference : this.RawReference; if(citeFunction != this.RawReference) { var workingstring = refText.match(/{{[\s]*(cite|Citation)[\s\S]*?}}/i)[0]; var match = refText.match(this.REF_REGEX); if(match && match != null) { var name = match[1] || match[2] || match[3]; // 3 possibilities, corresponding to above regex, are <ref name="foo">, <ref name='bar'>, and <ref name=baz> } var cutupstring = workingstring.split(/\|/g); // This little hack relies on the fact that 'e' appears first as the last letter of 'cite', and the type is next. if(citeFunction == this.CiteReference) { var beforeBar = cutupstring[0]; var typeStart = beforeBar.toLowerCase().indexOf('e'); // First end curly brace var rightCurly = beforeBar.indexOf('}'); // Usually, rightCurly will be -1. But this takes into account empty references like <ref>{{cite web}}</ref> var typeEnd = rightCurly != -1 ? rightCurly : beforeBar.length; // grab the type, then trim it. var type = $.trim(beforeBar.substring(typeStart + 1, typeEnd)); } } // type may be undefined, but that's okay. var citation = new citeFunction({"name": name, "type": type, "save": true, "inMWEditBox": true, "orig": refText}); if(citeFunction != this.RawReference) { var split = this.splitKeysAndValues(workingstring); var names = split.names; var values = split.values; for (var j = 0; j < names.length; j++) { /* Drop blank space, and |'s without params, which are never correct for citation templates.*/ var paramName = $.trim(names[j]).replace(/(?:\s*\|)*(.*)/, "$1"); var paramVal = $.trim(values[j]); // Should there be a setParam function? It could handle empty values, and even drop (siliently or otherwise) invalid parameters. Alternatively, should params be passed in the constructor? if (paramVal != "") { citation.params[paramName] = paramVal; } } } return citation; }, // TODO: Use https://gerrit.wikimedia.org/r/#/c/67166/ when merged. /** * Date-formatting class * * @param {String} format one of the format strings supported by MW core. * Currently, the supported values are 'default', 'mdy', 'dmy', 'ymd', and 'ISO 8601'. * If an unknown value is passed, it will use wgDefaultDateFormat. */ DateFormatter: function (format) { // 1-indexed (due to filler item at 0), in page content language. var monthNames = mw.config.get('wgMonthNames'); var supportedFormats = ['mdy', 'dmy', 'ymd', 'ISO 8601']; if($.inArray(format, supportedFormats) === -1) { format = mw.config.get('wgDefaultDateFormat'); } function getMonthName(date) { return monthNames[date.getMonth() + 1]; } this.formatAsMdy = function(date) { return getMonthName(date) + ' ' + date.getDate() + ', ' + date.getFullYear(); }; this.formatAsDmy = function(date) { return date.getDate() + ' ' + getMonthName(date) + ' ' + date.getFullYear(); }; this.formatAsYmd = function(date) { return date.getFullYear() + ' ' + getMonthName(date) + ' ' + date.getDate(); }; this.formatAsISO8601 = function(date) { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate(); }; var formatters = { mdy: this.formatAsMdy, dmy: this.formatAsDmy, ymd: this.formatAsYmd, 'ISO 8601': this.formatAsISO8601 }; /** * Formats date according to stored preference * * @param {Date} date date to format * * @return {String} formatted date as String */ this.format = function(date) { return formatters[format](date); }; }, /** * Root reference type. Parent of RawReference, CiteReference, and CitationReference. * @class AbstractReference * @for proveit * @constructor * @param {Object} argObj argument object with keys for each option */ AbstractReference: function(argObj) { // CiteReference has a non-trivial override of this. This is defined early (and conditionally) because it is used in the constructor. if(!this.setType) { /** * @param {String} type type of reference */ this.setType = function(type) { this.type = type; }; } /** * Update citation strings after changing reference. This runs after modifying a reference's fields (name, params), but before changing orig */ this.update = function() { var newCiteText = this.toString(); var strings = this.getCitationStrings(); /* * Update main citation in strings list. * * TODO: * Use strings array here to find and update citations that are not main references. As is, they are orphaned. * Both array and textbox should be updated. * It may be enough to just set all non-main citations in text and array to this.getInsertionText(false). * However, if they remove the name entirely (not recommended), that would be a problem. */ if(strings.length > 0) // This implies there was a name before { for(var i = 0; i < strings.length; i++) { // If we find the full citation as a citation, update to the new text. if(strings[i] == this.orig) { // this.orig itself is updated in updateInText strings[i] = newCiteText; } } } else if(this.name != null) // They have added a name, so we should have a main citation. { // Now that it has a name, it is a citation to itself. strings.push(newCiteText); } }; /** * &lt;ref name /&gt; for reference * @type String */ this.name = argObj.name != "" ? argObj.name : null; // Save blank names as null /* type of reference, e.g. cite web, cite news. Also used (including for CitationReference objects) to determine default fields. */ this.setType(argObj.type); //TODO: Re-examine whether both (or indeed either) of save or inMWEditBox are really necessary. Can it be determined from context? /** * flag to determine whether citation must be saved. false indicates "dirty" citation that has yet to be updated in text and metadata. * @type Boolean */ this.save = argObj.save; /** * true if and only if the ref is in the MW edit box with the same value as this object's orig. * @type Boolean */ this.inMWEditBox = argObj.inMWEditBox; /** * original wikitext for reference * @type String */ this.orig = argObj.orig; /** * mapping of parameter names to values * @type Object */ this.params = {}; /** * Convenience method. Returns sorter for parameters. * @return {Function} sorter for parameters */ this.getSorter = function() { var thisCite = this; // Make closure work as intended. // Sorter uses paramSortKey first, then falls back on alphabetical order. return function(paramA, paramB) { var aInd = thisCite.getSortIndex(paramA); var bInd = thisCite.getSortIndex(paramB); if(aInd != -1 && bInd != -1) { return aInd - bInd; } else { proveit.log('Parameter missing from getSortIndex, which causes the sort to be invalid. paramA: ', paramA, ', aInd: ', aInd, ', paramB: ', paramB, ', bInd: ', bInd); if(paramA < paramB) { return -1; } else if(paramA == paramB) { return 0; } else { return 1; } } }; }; /** * Returns true if this reference is valid, false otherwise. * Assume all AbstractReference objects are valid. Can be overridden in subtypes. * @return {Boolean} AbstractReference.isValid always returns true */ this.isValid = function(){return true;}; /** * Generates label for reference using title, author, etc. * @return {String} the label that was generated */ this.getLabel = function() { var label = ""; if (this.params.author) { label = this.params.author + "; "; } else if (this.params.last) { label = this.params.last; if (this.params.first) { label += ", " + this.params.first; } label += "; "; } if (this.params.title) { label += this.params.title; } if(label == "") { var value; for (value in this.params) { break; } if(value) // There could be no parameters { label = value; } } return label; }; /** * Gets insertion text (for edit box). * * TODO: Generate a regex object instead (getInsertionRegExp), so highlighting would not fail due to trivial changes (e.g. spacing). * @param {Boolean} full If true, insert full text, otherwise ref name only * @return {String} insertion text */ this.getInsertionText = function(full) { if(full) { return this.toString(); } else { if(this.name) { return "<ref name=\"" + this.name + "\" />"; } else { throw new Error("getInsertionText: ref.name is null"); } } }; /** * Updates this reference in the edit box. */ this.updateInText = function() { var txtarea = proveit.getTextbox(); if (!txtarea || txtarea == null) return; txtarea.focus(); var text = proveit.getTextboxText(); text = text.replace(this.orig, this.toString()); // Do replacement in textarea. txtarea.value = text; // Baseline for future modifications this.orig = this.toString(); this.save = true; proveit.highlightTargetString(this.toString()); }; /** * Internal helper method for toString. * @param {String} template template for ref (currently "cite" or "Citation" * @param {Boolean} includeType true to include this.type, false otherwise * @return {String} string for current reference */ this.toStringInternal = function(template, includeType) { if(this.name) { var returnstring = "<ref name=\"" + this.name + "\">"; } else { var returnstring = "<ref>"; } returnstring += "{{" + template + (includeType ? " " + this.type : ""); for (var name in this.params) { returnstring += " | " + name + "=" + this.params[name]; } returnstring += "}}</ref>"; return returnstring; }; /** * Array of citation strings for this reference. * @type Array */ this.citationStrings = []; /** * Sets citationStrings to an array * @param {Array} strings array of citation strings, not null */ this.setCitationStrings = function(strings) { this.citationStrings = strings; }; /** * Gets array of citationStrings. * @return {Array} (possibly empty) array of citation strings. Will not return null. */ this.getCitationStrings = function() { return this.citationStrings; }; /** * Get icon URL for reference * @return {String} icon URL */ this.getIcon = function() { return '//upload.wikimedia.org/wikipedia/commons/d/dd/Silk-Page_white.png'; }; }, /** * Constructor for CiteReference type. * @class CiteReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ CiteReference: function(argObj) { /* This is basically a fast representation of the template redirects, along with * self-mappings. */ var typeNameMappings = { web: "web", book: "book", journal: "journal", conference: "conference", encyclopedia: "encyclopedia", news: "news", newsgroup: "newsgroup", paper: "journal", "press release": "press release", "pressrelease": "press release", interview: "interview", episode: "episode", "AV media": "AV media", DVD: "AV media", audio: "AV media", "av media": "AV media", cd: "AV media", dvd: "AV media", media: "AV media", movie: "AV media", "music video": "AV media", video: "AV media", visual: "AV media" }; // Sets the type (e.g. web for cite web), applying the mappings. This is up top because it is used in AbstractReference constructor. this.setType = function(rawType) { var mappedType = typeNameMappings[rawType]; if(mappedType != null) this.type = mappedType; else this.type = rawType; // Use naive type as fallback. }; /** * Returns the type for display purposes, based on description messages. For example, for "AV media" it currently returns "Audiovisual work". * * @return {String} type for display */ this.getTypeForDisplay = function() { return proveit.getDescriptions()[this.type]; }; proveit.AbstractReference.call(this, argObj); // TODO: Should CiteReference.getSortIndex and CitationReference.getSortIndex be merged into AbstractCitation? Less fine-grained, but simpler to maintain. /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "url", "title", "trans_title", "encyclopedia", "publisher", "work", "date", "agency", "accessdate", "author", "last", "first", "subject", "subjectlink", "inventor", "editor", "author2", "last2", "first2", "subject2", "subjectlink2", "author3", "last3", "first3", "subject3", "subjectlink3", "author4", "last4", "first4", "subject4", "author5", "last5", "first5", "author6", "last6", "first6", "author7", "last7", "first7", "author8", "last8", "first8", "author9", "last9", "first9", "authorlink", "coauthors", "interviewer", "cointerviewers", "type", "newsgroup", "journal", "booktitle", "program", "episodelink", "series", "serieslink", "credits", "network", "station", "callsign", "city", "airdate", "began", "ended", "season", "seriesno", "number", "minutes", "transcript", "transcripturl", "people", "year", "month", "article", "contribution", "format", "medium", "newspaper", "conference", "volume", "edition", "issue", "location", "pages", "page", "language", "isbn", "issn", "oclc", "doi", "pmid", "id", "archiveurl", "archivedate", "deadurl", "time", "quote", "ref" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("cite", true); }; // References without these parameters will be flagged in red. // True indicates required (null, or undefined, means not required) var requiredParams = { web: { "url": true, "title": true}, book: { "title": true }, journal: { "title": true }, conference: { "title": true }, encyclopedia: { "title": true, "encyclopedia": true }, news: { "title": true, "work": true, "date": true }, newsgroup: { "title": true }, "press release" : { "title": true }, interview: { "last": true }, // TODO: Interview requires last *or* subject. Currently, we can't represent that. episode: { "title": true }, "AV media": { "title": true } }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { var curReq = requiredParams[this.type]; if(curReq) return curReq; else return {}; // Return empty object rather than null to avoid dereferencing null. }; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "title", "author", "accessdate", "work", "publisher", "date", "pages"], book: [ "title", "author", "authorlink", "year", "isbn", "publisher", "location", "pages", "url" ], journal: [ "title", "author", "journal", "volume", "issue", "year", "month", "pages", "url", "doi", "pmid" ], conference: [ "conference", "title", "booktitle", "author", "editor", "year", "month", "url", "id", "accessdate", "location", "pages", "publisher" ], encyclopedia: [ "title", "encyclopedia", "author", "editor", "accessdate", "edition", "year", "publisher", "volume", "location", "pages" ], news: [ "title", "author", "url", "work", "date", "accessdate", "pages", "location", "agency" ], newsgroup: [ "title", "author", "date", "newsgroup", "id", "url", "accessdate" ], "press release" : [ "title", "url", "publisher", "date", "accessdate" ], interview: ["last", "first", "subjectlink", "interviewer", "title", "callsign", "city", "date", "program", "accessdate"], episode: ["title", "series", "credits", "airdate", "city", "network", "season"], "AV media": ["people", "date", "url", "title", "medium", "location", "publisher"] }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { var curDefault = defaultParams[this.type]; if(curDefault) return curDefault; else return []; // Return empty array rather than null to avoid dereferencing null. }; this.isValid = function() { if(this.type == '') { return false; } var req = this.getRequiredParams(); var i = 0; var allFound = true; for(var reqParam in req) { /* Ignore parameters in req object that are null, undefined, or false. They are not required. */ if(!req[reqParam]) continue; allFound &= (reqParam in this.params); if(!allFound) break; } return allFound; }; var iconMapping = { web: "//upload.wikimedia.org/wikipedia/commons/f/f0/Silk-Page_white_world.png", book: "//upload.wikimedia.org/wikipedia/commons/1/1e/Silk-Book.png", journal: "//upload.wikimedia.org/wikipedia/commons/f/f8/Silk-Page_white_text.png", news: "//upload.wikimedia.org/wikipedia/commons/3/32/Silk-Newspaper.png", newsgroup: "//upload.wikimedia.org/wikipedia/commons/5/5c/Silk-Comments.png", "press release": "//upload.wikimedia.org/wikipedia/commons/b/bd/Silk-Transmit_blue.png", interview: "//upload.wikimedia.org/wikipedia/commons/f/f7/Silk-Telephone.png", episode: "//upload.wikimedia.org/wikipedia/commons/b/b2/Silk-Television.png", "AV media": "//upload.wikimedia.org/wikipedia/commons/1/1a/Silk-film.png" }; var superGetIcon = this.getIcon; this.getIcon = function() { var icon = iconMapping[this.type]; if(icon) { return icon; } return superGetIcon.call(this); }; }, /** * A function for citation style refs. * @class CitationReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj argument object with keys for each option */ CitationReference: function(argObj) { proveit.AbstractReference.call(this, argObj); // None currently required; var requiredParams = {}; // These paramaters will be auto-suggested when editing. var defaultParams = { web: [ "url", "author", "title", "date", "accessdate"], news: [ "author", "title", "newspaper", "url", "publication-place", "volume", "issue", "date", "pages"], encyclopedia: ["author", "editor", "contribution", "title", "publisher", "place", "year", "volume", "pages"], book: ["author", "title", "publisher", "place", "year"], journal: ["author", "title", "journal", "volume", "issue", "year", "pages"], patent: ["inventor", "title", "issue-date", "patent-number", "country-code"] }; /** * Returns the sort index for a given parameter * @param {String} param parameter name * @return {Number} sort index if found, otherwise -1 */ this.getSortIndex = function(param) { // This is the order fields will be displayed or outputted. return $.inArray(param, [ "last", "first", "url", "author", "editor", "contribution", "author-link", "last2", "first2", "author2-link", "publication-date", "inventor", "title", "issue-date", "patent-number", "country-code", "journal", "volume", "newspaper", "issue", "date", "publisher", "place", "year", "edition", "publication-place", "series", "version", "pages", "page", "id", "isbn", "doi", "oclc", "accessdate" ]); }; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.toStringInternal("Citation", false); }; /** * Return required parameters for this citation type. * @return {Object} object with required parameters as keys and true as value; empty object for unknown type */ this.getRequiredParams = function() { return requiredParams; }; /** * Returns default parameters (to be suggested when editing) for current reference * @return {Array} array of default parameter names; empty array if unknown */ this.getDefaultParams = function() { if(this.type) { return defaultParams[this.type]; } else { return ["url", "title", "author", "date", "publisher"]; // Can't determine more specific defaults when editing a pre-existing Citation. } }; }, /** * Constructor for RawReference type. * @class RawReference * @for proveit * @constructor * @extends AbstractReference * @param {Object} argObj the argument object, with keys for each option */ RawReference: function(argObj) { proveit.AbstractReference.call(this, argObj); this.type = 'raw'; /** * Returns this reference as a string. * @return {String} reference as string */ this.toString = function() { return this.orig; }; this.params['title'] = this.orig; this.getIcon = function() { return 'https://upload.wikimedia.org/wikipedia/commons/d/db/Silk-Page_white_code_red.png'; }; this.getTypeForDisplay = function() { return proveit.getDescriptions()['raw']; }; }, // TODO: This should be unified with changeRefFromEditPane /** * Convert the current contents of the add citation panel to a reference (i.e CiteReference(), CitationReference()) * @for proveit * @param {Node} box typepane root of add GUI (pane for specific type, e.g. journal) * @return {AbstractReference} ref or null if no panel exists yet. */ getReferenceFromAddPane: function(box) { var $box = $(box); var type = $box.data('proveitRefType'); // get <ref> name var refName = $('#addrefname').val(); var citeFunc = this.togglestyle ? this.CiteReference : this.CitationReference; var ref = new citeFunc({"name": refName, "type": type}); var paramName, paramVal; var paramList = $(".paramlist", box)[0]; var paramRows = $('div', paramList); for (var i = 0; i < paramRows.length; i++) { var paramRow = paramRows[i]; var valueTextbox = $(".paramvalue", paramRow)[0]; if($(paramRow).hasClass("addedrow")) // Added with "Add another field" { paramName = $.trim($(".paramdesc", paramRow)[0].value); } else { paramName = valueTextbox.id.substring(this.NEW_PARAM_PREFIX.length); } paramVal = $.trim(valueTextbox.value); if(paramName != "" && paramVal != "") { // Non-blank ref.params[paramName] = paramVal; } } ref.update(); return ref; }, /** * Called from the add citation panel, this is the function used to * add the actual citation. * * @param {AbstractReference} ref reference being added */ addReference: function(ref) { // get this working, lots of typing here. this.addNewElement(ref); ref.orig = ref.toString(); /* * Cycle through the boxes and grab the id's versus the values, watch * for the final box and make sure to grab the type as well */ this.insertRefIntoMWEditBox(ref, true); // true means insert full text here, regardless of global toggle. ref.save = true; ref.inMWEditBox = true; }, /** * Clear all rows of passed in add citation panes. * @param {Node} citePanes raw DOM element */ clearCitePanes: function(citePanes) { if(citePanes.hasChildNodes()) { citePanes.removeChild(citePanes.firstChild); } }, /** * Add event handler to Delete Field button in Add/Edit Reference panes * @param {Node} fieldRow the fieldRow DOM element to remove */ activateRemoveField: function(fieldRow) { $('.delete-field', fieldRow).click(function() { $(fieldRow).hide( 'highlight',{},'slow', function() { $(fieldRow).remove(); } ); }); }, /** * Changes the panel for the add reference panel to the correct type of entry * @param {Node} menu Raw HTML menu element */ changeAddPane: function(menu) { // Reset scroll $('#add-fields').scrollTop(0); $(menu.parentNode).show(); // cite/citation vbox. var citePanes = $(".addpanes", menu.parentNode.parentNode).get(0); this.clearCitePanes(citePanes); var newRefType = menu.value; var genPane = document.getElementById("dummyCitePane").cloneNode(true); var $genPane = $(genPane).attr('id', ''); $genPane.data('proveitRefType', newRefType); // name the ref-name-row $('.ref-name-row', $genPane).children('input').attr('id','addrefname'); $('.ref-name-row', $genPane).children('label').attr('for','addrefname'); // Somewhat hackish. What's a better way? var newRef; if(menu.id == "citemenu") { newRef = new this.CiteReference({}); } else { newRef = new this.CitationReference({}); } newRef.type = newRefType; var descs = this.getDescriptions(); var defaultParams = newRef.getDefaultParams().slice(0); // copy defaultParams.sort(newRef.getSorter()); //var required = newRef.getRequiredParams(); // Possibly, Cite objects should automatically include default parameters in their param maps. That would seem to make this simpler. for(var i = 0; i < defaultParams.length; i++) { newRef.params[defaultParams[i]] = ""; } // Should there be a getParamKeys or similar function for this, or even getSortedParamKeys? var newParams = []; for(param in newRef.params) { newParams.push(param); } newParams.sort(newRef.getSorter()); var required = newRef.getRequiredParams(); var paramList = $(".paramlist", $genPane)[0]; for(var i = 0; i < newParams.length; i++) { var param = newParams[i]; var paramBox; if(descs[param]) { paramBox = document.getElementById("preloadedparamrow").cloneNode(true); var label = $('.paramdesc', paramBox); if(required[param]) { label.addClass("required"); $('.delete-field', paramBox).remove(); // don't let people remove required fields } else { this.activateRemoveField(paramBox); } label.text(descs[param]); // Basically the same code as nameHbox above label.attr("for", this.NEW_PARAM_PREFIX + param); if(param == 'accessdate') $('.paramvalue', paramBox).val(this.dateFormatter.format(new Date)); } else { // Throwing an error here doesn't make sense if user-added fields can be copied over. // throw new Error("Undefined description for param: " + param); paramBox = document.getElementById("addedparamrow").cloneNode(true); var nameTextbox = $(".paramdesc", paramBox)[0]; nameTextbox.setAttribute("value", param); } paramBox.id = ""; this.activateRemoveField(paramBox); $(".paramvalue", paramBox)[0].id = this.NEW_PARAM_PREFIX + param; //paramBox.childNodes[2].value = newRef.params[param]; // Causes parameters to disappear. Why? paramList.appendChild(paramBox); } $(citePanes).prepend($genPane); }, /** * Creates and returns a hidden element holding the template elements * (placeholder elements later cloned and filled with real data) * * @return {jQuery} $root Hidden root element holding templates */ createTemplateElement: function() { var $root = $('<div>', { id: 'proveit-templates' }); // Dummy cite pane var dummyCite = $('<div>', { id: 'dummyCitePane', "class": 'typepane' }); var $addRefNameRow = this.createReferenceNameRow(); //$('input', $addRefNameRow).attr('id', 'addrefname'); //$('label', $addRefNameRow).attr('for', 'addrefname'); dummyCite.append($addRefNameRow); dummyCite.append($('<div>', {"class": 'paramlist'})); $root.append(dummyCite); var preloadedparam = $('<div>', { id: 'preloadedparamrow', "class": 'preloadedrow input-row' }).append($('<label>', { "class": 'paramdesc' })); var paramvalue = $('<input>', { "class": 'paramvalue', tabindex: 0 }); preloadedparam.append(paramvalue); var deleteButton = $('<button>', { "class": 'delete-field', tabindex: -1 }).text('delete field'); deleteButton.button({ icons: { primary: 'ui-icon-close' }, text: false }); preloadedparam.append(deleteButton); $root.append(preloadedparam); var addedparam = $('<div>', { id: 'addedparamrow', "class": 'addedrow input-row'}). append($('<input>', { "class": 'paramdesc', tabindex: 0 })). append(paramvalue.clone()). append(deleteButton.clone()); $root.append(addedparam); return $root; }, /** * Creates a row to be used to input name attribute of the ref (<ref name="..." />) * * @return {jQuery} <ref> name row */ createReferenceNameRow: function() { // div.ref-name-row var $refNameRow = $('<div>', { "class": 'ref-name-row', tabindex: -1 }); var refLabel = $('<label>', { "for": 'editrefname', title: 'This is a unique identifier that can be used to refer to this reference elsewhere on the page.', "class": 'paramdesc' }).text('<ref> name'); $refNameRow.append(refLabel); $refNameRow.append($('<input>', { id: 'editrefname', "class": 'paramvalue', tabindex: 0 })); return $refNameRow; }, /** * Create ProveIt HTML GUI */ createGUI: function() { if(this.getGUI().length > 0) { // GUI already created return false; } // more JqueryUI CSS: http://blog.jqueryui.com/2009/06/jquery-ui-172/ var gui = $('<div>', {id: this.GUI_ID}); var $tabs = $('<div>', {id: 'proveit-tabs'}); var created = $('<h1>'); var createdLink = $('<a>').attr({title: 'Created by the ELC Lab at Georgia Tech', href: 'http://proveit.cc.gatech.edu', target: '_blank'}); // Main logo in upper-right var logo = $('<img>' ).attr( {src: 'https://upload.wikimedia.org/wikipedia/commons/0/0d/ProveIt_user_interface_logo.png', alt: 'ProveIt', height: 30, width: 118 } ); createdLink.append(logo); created.append(createdLink); // Minimize/maximize button var showHideButton = $('<button>', { id: 'proveit-show-hide-toggle' } ).text('show/hide'); created.append(showHideButton); $tabs.append(created); var header = $('<ul>'); var view = $('<li>'); // View tab link var viewTab = $('<a/>', {id: 'proveit-view-tab', "class": 'tab-link', href: '#proveit-view-edit-panel'}).text('References ('); var numRefs = $('<span>').attr({id: 'numRefs'}).text('0'); viewTab.append(numRefs, ')'); view.append(viewTab); header.append(view); var add = $('<li>'); // Add tab link var addTab = $('<a>').attr({id: 'proveit-add-tab', "class": 'tab-link', href: '#proveit-add-panel'}).text('Add a Reference'); add.append(addTab); header.append(add); $tabs.append(header); // View and edit panel var viewEditPanel = $('<div>', {id: 'proveit-view-edit-panel'}); // View pane used for displaying references; within view tab var viewPane = $('<div>', {id: 'view-pane'}); var viewScroll = $('<div>', {"class": 'scroll', style: 'height: 210px;'}); // Ref list root element var refTable = $('<table>', {id: 'refs'}); var dummyRef = $('<tr>', {id: 'dummyRef', style: 'display: none;'}); dummyRef.append($('<td>', {"class": 'number'})). append($('<td>', {"class": 'type'})). append($('<td>', {"class": 'title'})); //append($('<td>', {"class": 'details'})); var editTd = $('<td>', {"class": 'edit'}). append($('<button>', {text: 'edit'})); dummyRef.append(editTd); refTable.append(dummyRef); viewScroll.append(refTable); viewPane.append(viewScroll); viewEditPanel.append(viewPane); // div#edit-pane, within view tab var editPane = $('<div>', {id: 'edit-pane', style: 'display: none'}); // div#edit-fields var editFields = $('<div>', {id: 'edit-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var refNameRow = this.createReferenceNameRow(); // div.paramlist var paramList = $('<div/>', {"class": 'paramlist'}); editFields.append(refNameRow); editFields.append(paramList); editPane.append(editFields); // div#edit-buttons, part of edit pane var editButtons = $('<div/>', {id: 'edit-buttons'}); var addFieldButton = $('<button/>', {style: 'margin-right: 50px;'}). append('add field'); editButtons.append(addFieldButton); var reqSpan = $('<span/>', {"class": 'required', text: 'bold'}); editButtons.append(reqSpan). append(' = required field'); var saveButton = $('<button/>', {"class": 'right-side accept', text: 'update edit form'}); editButtons.append(saveButton); var cancelButton = $('<button/>', {"class": 'right-side cancel', text: 'cancel'}); editButtons.append(cancelButton); editPane.append(editButtons); viewEditPanel.append(editPane); $tabs.append(viewEditPanel); // Add panel var addPanel = $('<div/>', {id: 'proveit-add-panel'}); var addFields = $('<div/>', {id: 'add-fields', "class": 'inputs scroll', style: 'height: 170px', tabindex: -1}); var cite = $('<div/>', {style: 'display: none', id: 'cite', "class": 'input-row'}); var refCiteTypeLabel = $('<label/>', {'for': 'citemenu', "class": 'paramdesc required', text: 'Reference type'}); cite.append(refCiteTypeLabel); var citemenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citemenu.get(0)); }}); var citeTypes = this.CiteReference.getTypes(); var descs = this.getDescriptions(); for(var i = 0; i < citeTypes.length; i++) { citemenu.append($('<option/>', {value: citeTypes[i], text: descs[citeTypes[i]]})); } cite.append(citemenu); addFields.append(cite); addFields.append($('<div/>', {"class": 'addpanes', id: 'citepanes', tabindex: -1})); var citation = $('<div/>', {style: 'display: none', id: 'citation', "class": 'input-row'}); var refCitationTypeLabel = refCiteTypeLabel.clone().attr('for', 'citationmenu'); citation.append(refCitationTypeLabel); var citationmenu = $('<select/>', {id: 'citemenu', change: function() { proveit.changeAddPane(citationmenu.get(0)); }}); var citationTypes = ['web', 'book', 'journal', 'encyclopedia', 'news', 'patent']; for(var j = 0; j < citationTypes.length; j++) { citationmenu.append($('<option/>', {value: citationTypes[i], text: descs[citationTypes[i]]})); } citation.append(citationmenu); addFields.append(citation). append($('<div/>', {"class": 'addpanes', id: 'citationpanes', style: 'display: none;'})); addPanel.append(addFields); // Add buttons, part of add tab var addButtons = $('<div/>', {id: 'add-buttons'}); addButtons.append($('<button/>', {style: 'margin-right: 50px;', text: 'add field'})). append(reqSpan.clone()). append(" = required"). append(saveButton.clone().text('insert into edit form')). append(cancelButton.clone()); addPanel.append(addButtons); $tabs.append(addPanel); gui.append($tabs); $(document.body).prepend(gui); var cancelEdit = function() { $("#edit-pane").hide(); $("#view-pane").show(); }; // set up tabs $tabs.tabs({ collapsible: true, active: false, // Initially all collapsed beforeActivate: function(event, ui) { // TODO: Select just-added item in reference list, upon moving from add tab to view tab // Is this event caused by a click on a tab? var isClickOnTab = event.currentTarget && $(event.currentTarget).is('.tab-link'); // Moving to add (including maximizing) if(ui.newPanel.is(addPanel)) { cancelEdit(); proveit.changeAddPane(document.getElementById(proveit.togglestyle ? 'citemenu' : 'citationmenu')); } if(ui.newPanel.length === 0) { if(isClickOnTab) { // Don't allow collapsing by clicking a tab. event.preventDefault(); // Clicked view tab when either view or edit was showing if(ui.oldPanel.is(viewEditPanel)) { // Cancel the edit and show reference list cancelEdit(); } } else { // They clicked the show/hide button; let it collapse and update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-n' } ); } } else { // There is a visible new panel; update the icon. showHideButton.button("option", "icons", { primary: 'ui-icon-triangle-1-s' } ); } } }); // add panel buttons $("#add-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow(document.getElementById("proveit-add-panel")); }) .next().next().button({ icons: { primary: 'ui-icon-circle-check', secondary: 'ui-icon-circle-arrow-e' } }).click(function() { proveit.addReference(proveit.getReferenceFromAddPane($('#proveit-add-panel .typepane').get(0))); $tabs.tabs( { active: 0 } ); // Activate view panel $("div.scroll, #view-pane").scrollTop(100000); // scroll to new ref }).next(). button({ icons: { primary: 'ui-icon-circle-close' } }).click(function() { $tabs.tabs( { active: 0 } ); // Activate view panel }); // cancel buttons $("button.cancel").click(cancelEdit); // edit panel buttons $("#edit-buttons button:first").button({ icons: { primary: 'ui-icon-circle-plus' } }).click(function() { proveit.addPaneRow($("#edit-pane")); }). next().next(). button({ icons: { primary: 'ui-icon-circle-check' } }).next().button({ icons: { primary: 'ui-icon-circle-close' } }); // create the minimize button showHideButton.button({ icons: { primary: 'ui-icon-triangle-1-n' }, text: false }); var viewAndAdd = $(viewEditPanel).add(addPanel); this.viewAndAddPanes = viewAndAdd; var prevActiveTabPaneIndex = 0; function minimize() { prevActiveTabPaneIndex = $tabs.tabs('option', 'active'); // Collapse all tabs $tabs.tabs('option', 'active', false); } function maximize() { $tabs.tabs('option', 'active', prevActiveTabPaneIndex); } this.toggleViewAddVisibility = function() { // All tabs collapsed if($tabs.tabs('option', 'active') === false) { maximize(); } else { minimize(); } }; showHideButton.click(this.toggleViewAddVisibility); this.scanForReferences(); $("#refs tr").eq(0).click().click(); // select first item in list. TODO: Why two .click? // alternate row colors $("#refs tr:even").addClass('light'); $("#refs tr:odd").addClass('dark'); gui.append(this.createTemplateElement()); }, /** * A reference to the set containing two items, the view and add tabs. Will be initialized by createGUI, so it is non-null if ProveIt is visible * * @type {$NodeSet} */ viewAndAddPanes: null, /* * Gets jQuery set for ProveIt GUI, which will be empty if ProveIt has not initialized * * @return {$Node} root of ProveIt */ getGUI: function() { return $('#' + this.GUI_ID); }, /** * Hides ProveIt completely */ hide: function() { this.getGUI().hide(); }, /** * Show ProveIt */ show: function() { this.createGUI(); this.getGUI().show(); }, /** * Toggle overall visiblility. If currently hidden, go to minimized. If minimized, maximize. If maximize, hide */ toggleVisibility: function() { if(this.getGUI().is(':visible')) { if(this.viewAndAddPanes.is(':visible')) // maximized { this.hide(); } /* * If previously maximized, we minimize after hiding, so when we show, it will already be minimized. * If minimized, we maximize */ this.toggleViewAddVisibility(); } else { this.show(); } }, /** * Toggle visibility of view and add panes. Initialized by createGUI * * @method toggleViewAddVisibility */ toggleViewAddVisibility: null, /** * Generates refbox row and all children, to be used by addNewElement, and when updating * * @param {AbstractReference} ref reference to generate from * @param {Boolean} isReplacement if true, this replaces another refbox item, so no number will be assigned, and the count will not be updated. * @return {Node} new refbox row for refbox */ makeReferenceBoxRow: function(ref, isReplacement) { var refName = ref.name; //may be null or blank //var refbox = this.getReferenceBox(); var newchild = $('<tr><td class="number"></td><td class="type"></td><td class="title"></td><td class="edit"></td></tr>').get(0); // removed <span class="pointers"></span> // removed <td class="details"></td> if(!ref.isValid()) { // Flag as invalid. $(newchild).addClass('invalid'); } // grab the nodes that need changed out of it var neweditimage = $('.edit button', newchild).get(0); var thisproveit = this; var title = ''; var shortTitle = ''; if(ref.params['title'] != null) { title = ref.params['title']; shortTitle = this.truncateTitle(title); } $('td.title', newchild).text(shortTitle); $('td.title', newchild).attr('title', title); // deal with variations of date info var formattedYear = ''; if(ref.params['year']) formattedYear = ref.params['year']; else if (ref.params['date']) { var yearMatch = ref.params['date'].match(/^([12]\d{3})/); if(yearMatch) { formattedYear = yearMatch[1]; } } //$('td.year', newchild).text(formattedYear); // deal with variations of author info var formattedAuthor = ''; if(ref.params['author']) formattedAuthor = ref.params['author']; else if (ref.params['last']) { // if(ref.params['first']) // formattedAuthor = ref.params['last'] + ', ' + ref.params['first']; // else formattedAuthor = ref.params['last']; } if(ref.params['coauthors'] || ref.params['last2']) formattedAuthor += ' <i>et al.</i>'; // build the "details" cell based on presence of author/year data // var details = ''; // if (formattedYear != '' && formattedAuthor != '') // details = '(' + formattedAuthor + ', ' + formattedYear + ')'; // else if (formattedYear != '') // details = '(' + formattedYear + ')'; // else if (formattedAuthor != '') // details = '(' + formattedAuthor + ')'; // $('td.details', newchild).html(details); // generate a URL based on ref type var icon = ref.getIcon(), url = '', refType = ref.type; switch(refType) { case 'web': url = ref.params['url']; break; case 'book': if(ref.params['isbn'] != null) url = mw.util.getUrl( 'Special:BookSources', { isbn: ref.params['isbn'] } ); break; case 'journal': case 'conference': if(ref.params['doi'] != null) url = 'http://dx.doi.org/' + ref.params['doi']; break; case 'news': url = ref.params['url']; break; case 'episode': url = 'http://www.imdb.com/find?s=ep&q=' + escape(ref.params['title']); break; } $('td.type', newchild).css('background-image','url('+icon+')'); var authorByline = '', yearByline = '', refTypeByline = ''; if(formattedAuthor != '') authorByline = 'By: <span class="author">' + formattedAuthor + '</span>'; if(formattedYear != '') yearByline = 'Date: <span class="date">' + formattedYear + '</span>'; if(refType != null) { var displayType = ref.getTypeForDisplay(), formattedRefType = displayType; $('td.type', newchild).attr('title', displayType); if(url != '') formattedRefType = '<a href="' + url + '" target="_blank">' + formattedRefType + '</a>'; refTypeByline = 'Type: <span class="type">' + formattedRefType + '</span>'; } //alert("authorByline: " + authorByline + "\n yearByline: " + yearByline + "\n refTypeByline: " + refTypeByline); var byline = '', separator = ' | '; if(refType == 'raw') { byline = refTypeByline + separator + mw.html.escape(ref.toString()); } else if(authorByline != '') // a?? { if(yearByline != '') // ad? { if(refTypeByline != '') // adt byline = authorByline + separator + yearByline + separator + refTypeByline; else // ad- byline = authorByline + separator + yearByline; } else // a-? { if(refTypeByline != '') // a-t byline = authorByline + separator + refTypeByline; else // a-- byline = authorByline; } } else // -?? { if(yearByline != '') // -d? { if(refTypeByline != '') // -dt byline = yearByline + separator + refTypeByline; else // -d- byline = yearByline; } else // --? { if(refTypeByline != '') // --t byline = refTypeByline; // no need for --- } } byline = '<p>' + byline + '</p>'; //alert(byline); // create expanded <div> var expanded = $('<div />',{ "class": 'expanded' }); // append the infobar to the expanded info box $(expanded).append(byline); // append the expanded info box to the title <td> $('td.title', newchild).append(expanded); if(!isReplacement) { // get ref number by counting number of refs (this includes dummy ref, but not the one we're creating) var numRefs = $('#refs tr').length; $('td.number', newchild).text(numRefs); $('#numRefs').text(numRefs); // update the number of refs in the view tab } // event handler for selecting a ref) $(newchild).click(function() { thisproveit.highlightTargetString(ref.orig); //thisproveit.highlightTargetString(ref.orig); $("#refs tr").removeClass('selected'); $(newchild).addClass('selected'); }); var doEdit = function() { thisproveit.updateEditPane(ref); $("#view-pane").hide(); $("#edit-pane").show(); }; var citationStrings = ref.getCitationStrings(); //var pointers = $('.pointers', newchild); var allCitations = $('<span class="all-citations" />'); for(var i = 0; i < citationStrings.length; i++) { var dividend = i + 1; var colName = ""; while(dividend > 0) { var mod = --dividend % 26; colName = String.fromCharCode(97 + mod) + colName; // a = 97 dividend = Math.floor(dividend / 26); } var citationHolder = $('<a href="#">' + colName + '</a>'); // Bind i var clickFunc = (function(i) { return function() { var last = 0, j = 0; var text = proveit.getTextboxText(); for(j = 0; j < i; j++) { last = text.indexOf(citationStrings[j], last); // Shouldn't happen. Indicates citation strings are out of date. if(last == -1) { proveit.log("citationStrings[" + j + "]: " + citationStrings[j] + " not found. Returning."); return false; } last += citationStrings[j].length; } var startInd = text.indexOf(citationStrings[i], last); if(startInd == -1) { proveit.log("citationStrings[" + i + "]: " + citationStrings[i] + " not found."); } else { proveit.highlightLengthAtIndex(startInd, citationStrings[i].length); } return false; }; })(i); citationHolder.click(clickFunc); allCitations.append(citationHolder); } if(citationStrings.length > 1) { var newP = $('<p />'); newP.append('This reference is cited in the article <span class="num-citations">' + citationStrings.length + ' times</span>: ').append(allCitations); expanded.append(newP); } // edit buttons if(ref.type != 'raw') { // SMALL EDIT BUTTON // create button var smallEditBtn = $('<button />',{ text: 'edit' }); // transform button $(smallEditBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); // button click event handler smallEditBtn.click(doEdit); // append button $('.edit', newchild).append(smallEditBtn); // LARGE EDIT BUTTON // create button var editBtn = $('<button />',{ "class": 'edit', text: 'edit this reference' }); // transform button $(editBtn).button({ icons: { primary: 'ui-icon-pencil' }, text: true }); // button click event handler editBtn.click(doEdit); // append button expanded.append(editBtn); // ROW EVENT HANDLER $(newchild).dblclick(doEdit); } else { // needed to keep all rows the same height $('.edit', newchild).append('&nbsp;'); } // ibid button if(citationStrings.length > 0) { // create button var ibidBtn = $('<button />',{ "class": 'insert', text: 'insert this reference at cursor' }); // transform button $(ibidBtn).button({ icons: { primary: 'ui-icon-arrowthick-1-e' }, text: true }); // button click event handler ibidBtn.click(function(){ thisproveit.insertRefIntoMWEditBox(ref, false); return false; }); // append button expanded.append(ibidBtn); } return newchild; }, /** * Truncates title to fit ProveIt refbox row. * @param {String} title title to truncate * @return {String} truncated title */ truncateTitle: function(title) { var MAX_LENGTH = 86; var truncated = title; if(title.length > MAX_LENGTH) { truncated = truncated.substring(0, MAX_LENGTH); var lastSpacePos = truncated.lastIndexOf(' '); if(lastSpacePos != -1) { truncated = truncated.substr(0, lastSpacePos); truncated += " ..."; } } return truncated; }, /** * Only to be used internally to add the citations to the list * * @param {AbstractReference} ref the reference to add */ addNewElement: function(ref) { var refbox = this.getReferenceBox(); $(refbox).append(this.makeReferenceBoxRow(ref, false)); } }, window.proveit); /** * Static method. Returns valid Cite reference types * @for CiteReference * @static * @return {Array} array of cite method types */ proveit.CiteReference.getTypes = function() { return ["web", "book", "journal", "conference", "encyclopedia", "news", "newsgroup", "press release", "interview", "episode", "AV media"]; }; proveit.split._compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group proveit.split._nativeSplit = String.prototype.split; proveit.setup(); }( mediaWiki, jQuery ) ); // Local Variables: // js2-basic-offset: 8 // End: hnr0117q2elln4cdploj302nqdduy42 360758 360757 2016-11-09T16:27:08Z en>Sophivorus 0 360758 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite web' ] }); // Load the dependencies mw.loader.using([ 'jquery.cookie', 'jquery.textSelection', 'jquery.ui.draggable' ]).then( function () { // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&action=raw&ctype=text/javascript' ); mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&action=raw&ctype=text/css', 'text/css' ); }); } } } d0sj1e3rzn75myh7k61njod2xhvtn1c 360759 360758 2017-02-07T11:13:21Z en>Sophivorus 0 Add templates 360759 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the dependencies mw.loader.using([ 'jquery.cookie', 'jquery.textSelection', 'jquery.ui.draggable' ]).then( function () { // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&action=raw&ctype=text/javascript' ); mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&action=raw&ctype=text/css', 'text/css' ); }); } } } 0ifcg9rjk5101on7rki5ehd2azaqf7j 360760 360759 2017-02-07T14:18:55Z en>Sophivorus 0 Remove redirect 360760 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite web' ] }); // Load the dependencies mw.loader.using([ 'jquery.cookie', 'jquery.textSelection', 'jquery.ui.draggable' ]).then( function () { // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&action=raw&ctype=text/javascript' ); mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&action=raw&ctype=text/css', 'text/css' ); }); } } } 5j8ncw28hp02fpdguf4n55s88i1b9nv 360761 360760 2017-03-02T22:16:52Z en>Sophivorus 0 360761 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite web' ] }); // Load the dependencies mw.loader.using([ 'jquery.cookie', 'jquery.textSelection', 'jquery.ui.draggable' ]).then( function () { // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&action=raw&ctype=text/javascript' ); mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&action=raw&ctype=text/css', 'text/css' ); }); } } } e8uhz1u98vj0nakzya29wpvtciiso53 360762 360761 2017-03-23T17:31:13Z en>Sophivorus 0 Add [[Template:Cite video]] 360762 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the dependencies mw.loader.using([ 'jquery.cookie', 'jquery.textSelection', 'jquery.ui.draggable' ]).then( function () { // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.js&action=raw&ctype=text/javascript' ); mw.loader.load( '//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt.css&action=raw&ctype=text/css', 'text/css' ); }); } } } rgasr3ltjyo7tw1nz4xq6bjsgdqppxa 360763 360762 2017-04-15T14:18:29Z en>Sophivorus 0 Update to minified calls 360763 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the dependencies mw.loader.using([ 'jquery.cookie', 'jquery.textSelection', 'jquery.ui.draggable' ]).then( function () { // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); }); } } } k7elsljil7xl19hi841ap1tkxxih80a 360764 360763 2017-04-18T19:28:55Z en>Sophivorus 0 Remove unnecessary dependency loads 360764 javascript text/javascript /** * ProveIt is a powerful GUI tool to find, edit, add and cite references in any MediaWiki wiki * Full documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget itself is loaded directly from Commons, but here are a few conditions to minimize requests * and a few configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Set the wiki-specific options (all options are optional and can be set to null) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } } } 54b77coxersbx378k9rlx1c4n86uh83 360765 360764 2018-01-30T13:54:17Z en>Sophivorus 0 Update to latest 360765 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few conditionals to minimize requests * and some configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only with the basic wikitext editor and the classic wikieditor, not the new one var textbox = $( '#wpTextbox1' ); if ( textbox.length ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Configure the gadget (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } } } } 03wblwobgpuho1w939scyxq5vvqqswy 360766 360765 2018-01-30T22:02:17Z en>Sophivorus 0 Update to latest 360766 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few conditionals to minimize requests * and some configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only with the basic wikitext editor and the classic wikieditor, not the new one var textbox = document.getElementById( 'wpTextbox1' ); if ( textbox ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Configure the gadget (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } } } } 74ujcpvsmktwy4k5l3odj9uibclygfw 360767 101975 2019-04-04T08:03:49Z en>TheDJ 0 add 4 new cite templates to prove it, per talk page request 360767 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few conditionals to minimize requests * and some configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only with the basic wikitext editor and the classic wikieditor, not the new one var textbox = document.getElementById( 'wpTextbox1' ); if ( textbox ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Configure the gadget (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } } } } 07ltxn03hkuyztqyijrra0b8wcmulvv 360768 360767 2019-08-02T14:20:14Z en>Sophivorus 0 Add Cite comic, Cite speech and Cite video game 360768 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few conditionals to minimize requests * and some configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only with the basic wikitext editor and the classic wikieditor, not the new one var textbox = document.getElementById( 'wpTextbox1' ); if ( textbox ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Configure the gadget (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } } } } lml6c95yng2s930j173gtzsqzm7mr32 360769 360768 2019-09-03T16:04:04Z en>Sophivorus 0 Update to latest version 360769 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few checks to minimize requests * and some configuration options specific to this wiki */ $( function () { // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { loadProveIt(); } mw.hook( 've.activationComplete' ).add( function () { if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } else { $( '#proveit' ).remove(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } }); function loadProveIt() { // Configuration options specific to this wiki (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag already created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } 56okz45xozubltptfgt2v7jyrqrnihc 360770 360769 2019-09-03T16:05:08Z en>Sophivorus 0 Undid revision 913847923 by [[Special:Contributions/Sophivorus|Sophivorus]] ([[User talk:Sophivorus|talk]]) 360770 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few conditionals to minimize requests * and some configuration options specific to this wiki */ // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { // Only with the basic wikitext editor and the classic wikieditor, not the new one var textbox = document.getElementById( 'wpTextbox1' ); if ( textbox ) { // Only load when editing wikitext (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Configure the gadget (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } } } } lml6c95yng2s930j173gtzsqzm7mr32 360771 360770 2019-09-03T16:26:53Z en>Sophivorus 0 Now yes, update to latest 360771 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons, * but here are a few checks to minimize requests * and some configuration options specific to this wiki */ $( function () { // Only load on appropriate namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on when editing var action = mw.config.get( 'wgAction' ); if ( action === 'edit' || action === 'submit' ) { loadProveIt(); } mw.hook( 've.activationComplete' ).add( function () { if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } else { $( '#proveit' ).remove(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } }); function loadProveIt() { // Configuration options specific to this wiki (all options are optional) mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag already created at Special:Tags 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt 'proveit-templates': [ // These templates should have their TemplateData defined 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); // Load the latest code directly from Commons mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } 56okz45xozubltptfgt2v7jyrqrnihc 360772 360771 2019-09-13T16:53:36Z en>Sophivorus 0 Update to latest version 360772 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons * This is the loader with some checks to minimize requests * and the configuration options specific to this wiki */ $( function () { // Only load on some namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on wikitext editors mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( function () { if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } else { $( '#proveit' ).remove(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } }); function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Edit summary automatically added by ProveIt (optional) 'proveit-templates': [ // Citation templates with their template data defined (recommended) 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } kpc0aqo9r29smplyrqxquxkvxfj0wbs 360773 360772 2019-09-13T16:54:24Z en>Sophivorus 0 360773 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons * This is the loader with some checks to minimize requests * and the configuration options specific to this wiki */ $( function () { // Only load on some namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on wikitext editors mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( function () { if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } else { $( '#proveit' ).remove(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } }); function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates with their template data defined (recommended) 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } 2nn04zt4n1vjxiooni5s6bhwy4zovnx 360774 360773 2019-09-13T16:59:30Z en>Sophivorus 0 360774 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons * This is the loader with some checks to minimize requests * and the configuration options specific to this wiki */ $( function () { // Only load on some namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on wikitext editors mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( function () { $( '#proveit' ).remove(); if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } }); function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates with their template data defined (recommended) 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } 0j7k4r8xrkfkvmn82yt5w0zmt1cmsn1 360775 360774 2019-09-13T17:12:13Z en>Sophivorus 0 360775 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons * This is just the loader with some checks to minimize requests * and the configuration options specific to this wiki */ $( function () { // Only load on some namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on wikitext editors mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( function () { $( '#proveit' ).remove(); if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } }); function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates with their template data defined (recommended) 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } l9k0aeqb2cyea6ls11cok0712asuycz 360776 360775 2019-09-13T17:18:07Z en>Sophivorus 0 Update to latest version 360776 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * The gadget code is loaded directly from Wikimedia Commons * This code is just the loader with some checks to minimize requests * and the configuration options specific to this wiki */ // Only load on some namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on wikitext editors mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( function () { $( '#proveit' ).remove(); if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag created at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates with their template data defined (recommended) 'Template:Citation', 'Template:Cite arXiv', 'Template:Cite AV media', 'Template:Cite book', 'Template:Cite bioRxiv', 'Template:Cite comic', 'Template:Cite encyclopedia', 'Template:Cite episode', 'Template:Cite interview', 'Template:Cite journal', 'Template:Cite magazine', 'Template:Cite news', 'Template:Cite paper', 'Template:Cite press release', 'Template:Cite report', 'Template:Cite sign', 'Template:Cite speech', 'Template:Cite thesis', 'Template:Cite tweet', 'Template:Cite video', 'Template:Cite video game', 'Template:Cite web' ] }); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.js&action=raw&ctype=text/javascript' ); mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ProveIt2.css&action=raw&ctype=text/css', 'text/css' ); } sqa499jc8041hu3i6ax2zpzcbskbnu3 360777 360776 2019-09-25T00:27:49Z en>Sophivorus 0 Update to latest version 360777 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Central documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This page sets the configuration options specific to this wiki * and then loads the latest gadget code directly from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite book', 'Cite bioRxiv', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite news', 'Cite paper', 'Cite press release', 'Cite report', 'Cite sign', 'Cite speech', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite web', ] }); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load on some namespaces var namespace = mw.config.get( 'wgNamespaceNumber' ); if ( namespace === 0 || namespace === 2 || namespace === 118 ) { // Only load on wikitext pages (and not in common.js or common.css, for example) var contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'wikitext' ) { // Only load on wikitext editors mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( function () { $( '#proveit' ).remove(); if ( ve.init.target.getSurface().getMode() === 'source' ) { loadProveIt(); } }); mw.hook( 've.deactivationComplete' ).add( function () { $( '#proveit' ).remove(); }); } } 4bvh8w3kuj30tirsfgh6vskuqa4ptot 360778 360777 2019-09-25T14:22:21Z en>Sophivorus 0 Update to latest version 360778 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite book', 'Cite bioRxiv', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite news', 'Cite paper', 'Cite press release', 'Cite report', 'Cite sign', 'Cite speech', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ] }); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); 08wj2x0vhhvcaboz83p423clvh91crv 360779 105459 2019-10-15T13:52:55Z en>Sophivorus 0 Add missing templates from [[Category:Citation Style 1 templates]] 360779 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ] }); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); iph33z7s8h99httj13e28it9hywgioo 360780 360779 2023-01-06T14:07:24Z en>Sophivorus 0 Prefer lowercase template names, see https://en.wikipedia.org/wiki/Wikipedia_talk:ProveIt#Capitalising_citation_template_names 360780 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'citation', 'cite arXiv', 'cite AV media', 'cite AV media notes', 'cite book', 'cite bioRxiv', 'cite conference', 'cite comic', 'cite encyclopedia', 'cite episode', 'cite interview', 'cite journal', 'cite magazine', 'cite mailing list', 'cite map', 'cite news', 'cite newsgroup', 'cite paper', 'cite podcast', 'cite press release', 'cite report', 'cite serial', 'cite sign', 'cite speech', 'cite techreport', 'cite thesis', 'cite tweet', 'cite video', 'cite video game', 'cite ssrn', 'cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ] }); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); l469tty51x0ksyr39cnowaq08czuyeb 360781 360780 2023-01-06T14:16:02Z en>Sophivorus 0 Undid revision 1131941088 by [[Special:Contributions/Sophivorus|Sophivorus]] ([[User talk:Sophivorus|talk]]) Wrong approach, should be done from https://commons.wikimedia.org/wiki/MediaWiki:Gadget-ProveIt.js 360781 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ] }); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); iph33z7s8h99httj13e28it9hywgioo 360782 360781 2023-07-29T19:58:46Z en>Izno 0 [[phab:T337149#8953569]] 360782 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ] }); mw.loader.load( 'https://commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( 'https://commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); i3o83dzffm9j7qoebslj2lov4xq8trl 360783 360782 2023-10-03T20:10:34Z en>Sophivorus 0 Add [[Template:Cite Instagram]] 360783 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ] }); mw.loader.load( 'https://commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( 'https://commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); 6j1y7u6ve9updorkz1sde7exnv1vgwc 360784 360783 2023-12-01T11:17:20Z en>Sophivorus 0 Add warning for cosmetic changes, see [[Wikipedia talk:ProveIt#Consistency for work parameter]] 360784 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( 'https://commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( 'https://commons.wikimedia.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); rdvs5bj540is5jq1tg7y7ckwu3tn9el 360785 360784 2024-01-07T21:16:39Z en>Sophivorus 0 Update remote loading URLs 360785 javascript text/javascript /** * ProveIt is a powerful reference manager for Wikipedia * Documentation at https://commons.wikimedia.org/wiki/Help:Gadget-ProveIt * * This script sets the configuration options specific to this wiki * and loads the gadget code from Wikimedia Commons */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); ftj1408c5k4uh46r3t7mpkgbvj3s6di 360786 163916 2024-01-07T21:34:34Z en>Sophivorus 0 Update docs 360786 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); r9m3xmdlf229pd0tky455qt08i9islk 360787 163917 2024-03-07T20:47:54Z en>Sophivorus 0 Enable on template namespace for cases like [[Template:2024MERep]], see [[Wikipedia talk:ProveIt#Allow it to be used on Template pages]] 360787 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); 53o05agect2oson02pjghk5zx4vgy08 360788 360787 2025-03-05T14:31:44Z en>Sophivorus 0 Add [[Template:Cite Rotten Tomatoes]] and [[Template:Cite Metacritic]], see [[Wikipedia talk:ProveIt#Cite Rotten Tomatoes and Cite Metacritic]] 360788 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); n4zwgnx3qihoa2xilbumi8e0rth9bw3 360789 360788 2025-08-25T14:11:02Z en>Sophivorus 0 Add support for [[Template:Cite Q]], [[Template:R]] and [[Template:Sfn]] 360789 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', 'Cite Q', 'R', 'Sfn', ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); tven746bk8s6zjgwmggs1azwvlpbhx6 360790 360789 2025-08-29T12:59:47Z en>Sophivorus 0 Add support for [[Template:Sfnm]] 360790 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); 2ssfo4l8kj24xj0twcjl0b1bzfbi2nf 360791 360790 2025-09-01T15:12:46Z en>Sophivorus 0 Add support for [[Cite Hansard]], [[Cite newspaper The Times]], [[Cite ODNB]] and [[Template:Cite wikisource]], see [[Wikipedia talk:ProveIt#Please add]] 360791 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=scripts' ); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.ProveIt&only=styles', 'text/css' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( loadProveIt ); mw.hook( 've.activationComplete' ).add( loadProveIt ); 5xj5lqj331ukjo2ld0uygpkocxm37bm 360792 360791 2025-09-01T16:13:40Z en>Sophivorus 0 Update init code to load latest global version 360792 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': '<strong>Warning!</strong> Edits that <strong>only</strong> do cosmetic changes may be considered disruptive. See <a target="_blank" href="https://en.wikipedia.org/wiki/Wikipedia:COSMETICBOT">WP:COSMETICBOT</a> for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); 43cxsbnsphgd6ai05mqnes26waz2qr0 360793 360792 2025-09-01T16:22:32Z en>Sophivorus 0 Remove HTML from warning as no longer supported 360793 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation at https://www.mediawiki.org/wiki/ProveIt * * This initialization script sets the configuration options specific to this wiki * and then loads the ProveIt code directly from MediaWiki.org */ function loadProveIt() { mw.config.set({ 'proveit-tag': 'ProveIt edit', // Revision tag defined at Special:Tags (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Automatic edit summary (optional) 'proveit-templates': [ // Citation templates (without namespace) 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-namespaces': [ // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': 'Warning! Edits that ONLY do cosmetic changes may be considered disruptive. See WP:COSMETICBOT for more.' }); mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); sv6t2w73npym63uwlivutlt4n83nsnx 360794 360793 2025-09-04T15:08:34Z en>Sophivorus 0 Update style 360794 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set({ // Revision tag defined at Special:Tags (optional) 'proveit-tag': 'ProveIt edit', // Automatic edit summary (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 'proveit-namespaces': [ 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ], 'proveit-normalize-warning': 'Warning! Edits that ONLY do cosmetic changes may be considered disruptive. See WP:COSMETICBOT for more.' }); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); fqv4hzsfsy6qhrwitu1ct5239gjgs5n 360795 360794 2025-09-05T13:41:34Z en>Sophivorus 0 Remove 'proveit-normalize-warning' as it was moved to core 360795 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Revision tag defined at Special:Tags (optional) 'proveit-tag': 'ProveIt edit', // Automatic edit summary (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Supported namespaces (see https://www.mediawiki.org/wiki/Manual:Namespace_constants) 'proveit-namespaces': [ 0, // Main namespace 2, // User namespace 10, // Template namespace 118, // Draft namespace ] } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); hpobm3i3ohwlu5ua3qqrs8kz01kiqkb 360796 360795 2025-09-05T13:46:02Z en>Sophivorus 0 Remove 'proveit-namespaces' because they are now set from [[MediaWiki:Gadget-definitions]] 360796 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Revision tag defined at Special:Tags (optional) 'proveit-tag': 'ProveIt edit', // Automatic edit summary (optional) 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ] } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); o1ev4b3ma91ss3crssy3yj5ga40e6h0 360797 360796 2025-09-05T13:58:42Z en>Sophivorus 0 360797 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Revision tag defined at Special:Tags 'proveit-tag': 'ProveIt edit', // Automatic edit summary 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); 3m3u49cw387vcanhvtprtglf6u0z0rh 360798 218092 2025-09-08T13:18:42Z en>Sophivorus 0 Configure date format 360798 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Preferred date format, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options 'proveit-date-format': { year: 'numeric', month: 'long', day: 'numeric' }, // Revision tag defined at Special:Tags 'proveit-tag': 'ProveIt edit', // Automatic edit summary 'proveit-summary': 'Reference edited with [[Wikipedia:ProveIt|ProveIt]]', } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( editForm => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); py20sq1ivqkv8m4mximmqrr25vdrzre 360799 360727 2026-05-16T07:32:56Z ChiK 1136 ೭೧ revisions imported from [[:en:MediaWiki:Gadget-ProveIt.js]] 359667 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Local citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite book', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite journal', 'Cite news', 'Cite paper', 'Cite report', 'Cite sign', 'Cite speech', 'Cite thesis', 'Cite video', 'Cite web', 'R', 'Sfn', ], // Citation templates that shouldn't go inside <ref> tags //'proveit-templates-noref': [ 'R', 'Sfn' ], // Supported namespaces, see https://www.mediawiki.org/wiki/Manual:Namespace_constants //'proveit-namespaces': [ 0, 2 ], // Preferred date format, see https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options //'proveit-date-format': { year: 'numeric', month: 'numeric', day: 'numeric' }, // Revision tag defined at Special:Tags //'proveit-tag': 'proveit', // Automatic edit summary //'proveit-summary': 'Reference edited with [[mw:ProveIt|ProveIt]]', } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( () => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); hicuu8wi8894caqpc0bawx48e8g2h4l 360800 360799 2026-05-16T07:35:43Z ChiK 1136 360800 javascript text/javascript /** * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki * Documentation: https://www.mediawiki.org/wiki/ProveIt * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js */ function loadProveIt() { mw.config.set( { // Citation templates (without namespace) 'proveit-templates': [ 'Citation', 'Cite arXiv', 'Cite AV media', 'Cite AV media notes', 'Cite book', 'Cite bioRxiv', 'Cite conference', 'Cite comic', 'Cite encyclopedia', 'Cite episode', 'Cite Hansard', 'Cite Instagram', 'Cite interview', 'Cite journal', 'Cite magazine', 'Cite mailing list', 'Cite map', 'Cite Metacritic', 'Cite news', 'Cite newsgroup', 'Cite newspaper The Times', 'Cite ODNB', 'Cite paper', 'Cite podcast', 'Cite press release', 'Cite report', 'Cite Rotten Tomatoes', 'Cite serial', 'Cite sign', 'Cite speech', 'Cite techreport', 'Cite thesis', 'Cite tweet', 'Cite video', 'Cite video game', 'Cite ssrn', 'Cite wikisource', 'Cite web', 'Cite Q', 'R', 'Sfn', 'Sfnm' ], // Citation templates that shouldn't go inside <ref> tags 'proveit-templates-noref': [ 'R', 'Sfn', 'Sfnm' ], // Preferred date format, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options 'proveit-date-format': { year: 'numeric', month: 'long', day: 'numeric' }, // Revision tag defined at Special:Tags 'proveit-tag': 'ProveIt edit', // Automatic edit summary 'proveit-summary': 'Reference edited with [[mw:ProveIt|ProveIt]]', } ); // Load from the central, global version at MediaWiki.org mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt' ); } // Only load when editing mw.hook( 'wikipage.editform' ).add( () => window.ProveIt || loadProveIt() ); mw.hook( 've.newTarget' ).add( target => target.constructor.static.name === 'article' && target.on( 'surfaceReady', loadProveIt ) ); 52k1jneul73kxtvj02jzhys6vmirqqa ದ್ರೌಪದಿ ಮುರ್ಮು 0 12614 360710 359490 2026-05-16T07:08:01Z ChiK 1136 null #proveit 360710 wikitext text/x-wiki {{Infobox officeholder | name = '''ದ್ರೌಪದಿ ಮುರ್ಮು''' | image = President of India Droupadi Murmu official portrait (cropped).jpg | caption = | order = ಭಾರತದ ೧೫ನೇ | office = ರಾಷ್ಟ್ರಪತಿ | primeminister = [[ನರೇಂದ್ರ ಮೋದಿ]] | vicepresident = {{ubl|ಸಿ. ಪಿ. ರಾಧಾಕೃಷ್ಣನ್}} | term_start = ೨೫ನೇ ಜುಲೈ ೨೦೨೨ | term_end = | predecessor = [[ರಾಮನಾಥ ಕೋವಿಂದ್]] | successor = | office2 = ಝಾರ್ಖಂಡ್ ರಾಜ್ಯೊದ ೮ನೇ ರಾಜ್ಯಪಾಲೆ | term_start2 = ೧೮ನೇ ಮೇ ೨೦೧೫ | term_end2 = ೧೨ನೇ ಜುಲೈ ೨೦೨೧ | 1blankname2 = ಮುಖ್ಯಮಂತ್ರಿ | 1namedata2 = ರಘುಬರ್ ದಾಸ್<br />ಹೇಮಂತ್ ಸೊರೆನ್ | predecessor2 = ಸಯಿದ್ ಅಹ್ಮದ್ | successor2 = ರಮೇಶ್ ಭೈಸ್ | office3 = [[ಒಡಿಶಾ ಸರ್ಕಾರ|ಒಡಿಶಾ ರಾಜ್ಯ ಸಚಿವರು]]{{Infobox officeholder | embed = yes | status3 = ಸ್ವತಂತ್ರ ಜವಾಬ್ದಾರಿ | term_start3 = 6 ಆಗಸ್ಟ್ 2002 | term_end3 = 16 ಮೇ 2004 | 3blankname3 = [[ಒಡಿಶಾದ ಮುಖ್ಯಮಂತ್ರಿಗಳ ಪಟ್ಟಿ|ಮುಖ್ಯಮಂತ್ರಿ]] | 3namedata3 = [[ನವೀನ್ ಪಟ್ನಾಯಕ್]] | 4blankname3 = ಸಚಿವಾಲಯೊ | 4namedata3 = ಮೀನುಗಾರಿಕೆ ಬುಕ್ಕೊ ಪ್ರಾಣಿ ಸಂಪನ್ಮೂಲ ಅಭಿವೃದ್ಧಿ | predecessor3 = | successor3 = | 4blankname4 = ಸಚಿವಾಲಯೊ | 4namedata4 = ವಾಣಿಜ್ಯ ಬುಕ್ಕೊ ಸಾರಿಗೆ | 3blankname4 = [[ಒಡಿಶಾದ ಮುಖ್ಯಮಂತ್ರಿಗಳ ಪಟ್ಟಿ|ಮುಖ್ಯಮಂತ್ರಿ]] | 3namedata4 = [[ನವೀನ್ ಪಟ್ನಾಯಕ್]] | term_start4 = 6 ಮಾರ್ಚ್ 2000 | term_end4 = 6 ಆಗಸ್ಟ್ 2002 | predecessor4 = | successor4 = }} | office5 = [[ಒಡಿಶಾ ವಿಧಾನಸಭೆಯ ಸದಸ್ಯ (ಭಾರತ)|ಸದಸ್ಯ]] [[ಒಡಿಶಾ ವಿಧಾನಸಭೆಯ]] | term_start5 = 5 ಮಾರ್ಚ್ 2000 | term_end5 = 21 ಮೇ 2009 | predecessor5 = ಲಕ್ಷ್ಮಣ್ ಮಾಝಿ | successor5 = ಶ್ಯಾಮ್ ಚರಣ್ ಹಂಸದಾ | constituency5 = [[ರೈರಂಗಪುರ ವಿಧಾನಸಭಾ ಕ್ಷೇತ್ರ|ರೈರಂಗಪುರ]] | party = [[ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷ]] | birth_name = ದುರ್ಗಿ ಬಿರಾಂಚಿ ತುಡು | birth_date = {{birth date and age|df=y|1958|06|20}} | birth_place = ಉಪರಬೇಡ, [[ಮಯೂರ್ಭಂಜ್ ಜಿಲ್ಲೆ|ಮಯೂರ್ಭಂಜ್]], [[ಒಡಿಶಾ]], [[ಭಾರತ]] | spouse = {{marriage|Shyam Charan Murmu|1980||}} | children = 3<ref>{{Cite web |date=29 August 2022 |title=When Droupadi Murmu lost her husband, 2 sons {{!}} 5 things to know about her family |url=https://www.hindustantimes.com/india-news/when-droupadi-murmu-lost-her-husband-2-sons-5-things-to-know-about-her-family-101658386162861.html |access-date=29 August 2022 |website=Hindustan Times |language=en |archive-date=29 August 2022 |archive-url=https://web.archive.org/web/20220829043723/https://www.hindustantimes.com/india-news/when-droupadi-murmu-lost-her-husband-2-sons-5-things-to-know-about-her-family-101658386162861.html |url-status=live }}</ref> | education = | alma_mater = [[ಉತ್ಕಲ್ ವಿಶ್ವವಿದ್ಯಾಲಯ]] (ಬ್ಯಾಚುಲರ್ ಆಫ್ ಆರ್ಟ್ಸ್-ಬಿ.ಎ.) | occupation = ರಾಜಕಾರಣಿ | profession = ಶಿಕ್ಷಕ | website = {{URL|https://presidentofindia.nic.in/|Official website}} | residence = [[ರಾಷ್ಟ್ರಪತಿ ಭವನ|ರಾಷ್ಟ್ರಪತಿ ಭವನ, ನವದೆಹಲಿ]] | signature = Signature of Droupadi Murmu.svg }} '''ದ್ರೌಪದಿ ಮುರ್ಮು''' ಭಾರತೀಯ ರಾಜಕಾರಿಣಿ, ಮೆರ್ [[ಭಾರತ|ಭಾರತದ]] [[ಭಾರತದ ರಾಷ್ಟ್ರಪತಿ|ರಾಷ್ಟ್ರಪತಿ]]ಯಾದ್ ಆಯ್ಕೆ ಆತೆರ್. ಮೆರ್ ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷದ (ಬಿಜೆಪಿ) ಸದಸ್ಯೆ ಆದಿತ್ತೆರ್.[[ಭಾರತದ ರಾಷ್ಟ್ರಪತಿ|ಭಾರತದ ರಾಷ್ಟ್ರಪತಿಯಾದ್]] ಆಯ್ಕೆ ಆಯಿನ ಸ್ಥಳೀಯ, ಪರಿಶಿಷ್ಟ ಬುಡಕಟ್ಟು ಸಮುದಾಯೊಗು ಸೇರಿನ ಸುರುತ ಪೊಂಜೊವು. ಮೆರ್ ಅಧ್ಯಕ್ಷೆ ಆಪಿನ ಸುರುಕು ೨೦೧೫ ಬುಕ್ಕೊ ೨೦೨೧ನ ನಡುಟು ಜಾರ್ಖಂಡ್‌ದ ಒರ್ಂಭನೆ ರಾಜ್ಯಪಾಲರಾದ್ ಸೇವೆ ಮಲ್ತಿನಾರ್ ಅಂಚನೆ ೨೦೦೦ಡ್ದ್ ೨೦೦೪ದ ನಡುಟು ಒಡಿಶಾ ಸರ್ಕಾರದ ಕ್ಯಾಬಿನೆಟ್‌‌ಡ್ ಬೇತೆ ಬೇತೆ ಖಾತೆಲೆಡ್ ಇತ್ತಿನಾರ್. ರಾಜಕೀಯಗ್ ಪ್ರವೇಶ ಆಪಿನೆಗ್ ದುಂಬು ರಾಜ್ಯ ನೀರಾವರಿ ಬುಕ್ಕೊ ವಿದ್ಯುತ್ ಇಲಾಖೆಡ್ ಕಿರಿಯ ಸಹಾಯಕಿಯಾದ್‌ಲ ಅವೆಡ್ದ್ ಬುಕ್ಕೊ ರಾಯರಂಗಪುರದ ಶ್ರೀ ಅರಬಿಂದೋ ಸಮಗ್ರ ಶಿಕ್ಷಣ ಕೇಂದ್ರೊಡು ೧೯೯೭ ಮುಟ್ಟ ಶಿಕ್ಷಕಿಯಾಗಿ ಬೆಂದಿನಾರ್. ಜೂನ್ ೨೦೨೨ ಡ್ ಬಿಜೆಪಿ ದ್ರೌಪದಿ ಮುರ್ಮು ಮೆರೆನ್ ೨೦೨೨ದ ಚುನಾವಣೆಗೆ ರಾಷ್ಟ್ರೀಯ ಪ್ರಜಾಸತ್ತಾತ್ಮಕ ಒಕ್ಕೂಟದ (NDA) ಅಧ್ಯಕ್ಷೀಯ ಅಭ್ಯರ್ಥಿಯಾದ್ ನಾಮನಿರ್ದೇಶನ ಮಲ್ತ್ಂಡ್. ಅವೆಡ್ದ್ ಬುಕ್ಕೊ ಜುಲೈ ೨೦೨೨ ಡ್ ಅಧ್ಯಕ್ಷೆಯಾದ್ ಆಯ್ಕೆ ಆಯೆರ್, ದೇಶದ ಎಲ್ಯ ಪ್ರಾಯದ ಕಿರಿಯ ರಾಷ್ಟ್ರಪತಿ ಅಂಚನೆ ಭಾರತದ ಸ್ವಾತಂತ್ರ್ಯದ ಬುಕ್ಕೊ ಪುಟ್ಟಿನ ಸುರುತ ರಾಷ್ಟ್ರಪತಿಯಾದುಲ್ಲೆರ್ == ವೈಯಕ್ತಿಕ ಜೀವನ == ದ್ರೌಪದಿ ಮುರ್ಮು ಜೂನ್ 20, 1958 ಡ್ ಒಡಿಶಾದ ರೈರಂಗಪುರದ ಬೈದಪೋಸಿ ಪ್ರದೇಶೊಡು [[ಸಂತಾಲೆರ್|ಸಂತಾಲೆರೆ]] ಕುಟುಂಬೊಡು ಪುಟ್ಟಿಯೆರ್.ಆರೆನ ಅಮ್ಮೆರ್ ಬುಕ್ಕೊ ಅಜ್ಜೆರ್ ಗ್ರಾಮ ಪರಿಷತ್ತ್‌ದ ಸಾಂಪ್ರದಾಯಿಕ ಮುಖ್ಯಸ್ಥರಾದಿತ್ತೆರ್. ಮುರ್ಮು ರಮಾದೇವಿ ಮಹಿಳಾ ಕಾಲೇಜ್‌ಡ್ ಕಲಾ ಪದವಿ ಪಡೆಯೆರ್<ref>{{Cite web|url=https://www.prajavani.net/news/india-news/president-election-result-2022-draupadi-murmu-overcome-great-personal-tragedies-956339.html|title=President Of India: ದುರಂತಗಳನ್ನು ಮೆಟ್ಟಿ ನಿಂತ ದ್ರೌಪದಿ ಮುರ್ಮು|first=ಪ್ರಜಾವಾಣಿ ವೆಬ್‌|last=ಡೆಸ್ಕ್‌|website=Prajavani}}</ref>. ದ್ರೌಪದಿ ಮುರ್ಮು ಶ್ಯಾಮ್ ಚರಣ್ ಪನ್ಪಿ ಒರಿ ಬ್ಯಾಂಕರ್‌ನ್ ಮದಿಮೆ ಆದ್ ರಡ್ಡ್ ಆಣ್ ಜೋಕುಲು ಅಂಚನೆ ಒಂಜಿ ಪೊಣ್ಣು ಬಾಲೆನ್ ಪಡೆದ್ ಸುಖ ಸಂಸಾರಿಯಾದಿತ್ತೆರ್ .2009ಡ್ದ್ 2015ನೆ ಮುಟ್ಟದ 7 ವರ್ಷದ ಅವಧಿಡ್ ಆರೆನ ಕಂಡನಿ ಹೃದಯಾಘಾತಡ ಬುಕ್ಕೊ ರಡ್ಡ್ ಆಣ್ ಜೋಕುಲು, ಅಪ್ಪೆ ಬುಕ್ಕೊ ಒರಿ ಸಹೋದರನ ಮರಣ ಆಪುಂಡು. ಆರ್ ಬ್ರಹ್ಮ ಕುಮಾರೀಸ್ ಆಧ್ಯಾತ್ಮಿಕ ಚಳುವಳಿದ ಅನುಯಾಯಿನಿ ಆದಿತ್ತೆರ್. == ಸುರುತ ವೃತ್ತಿಜೀವನ == 1979 ಡ್ದ್ 1983 ಮುಟ್ಟ ಮುರ್ಮು ಒಡಿಶಾ ಸರ್ಕಾರದ ನೀರಾವರಿ ಇಲಾಖೆಡ್ ಕಿರಿಯ ಸಹಾಯಕೆರಾದ್ ಕೆಲಸ ಮಲ್ತೆರ್. ಅವೆಡ್ದ್ ಬುಕ್ಕೊ ಶಾಲೆಡ್ ಶ್ರೀ ಅರಬಿಂದೋ ಇಂಟೆಗ್ರಲ್ ಎಜುಕೇಶನ್ ಸೆಂಟರ್, ರೈರಂಗಪುರೊಟು ಶಿಕ್ಷಕಿಯಾದ್ ಕೆಲಸ ಮಲ್ತೆರ್ ಬುಕ್ಕೊ ಹಿಂದಿ, ಒಡಿಯಾ, ಗಣಿತ ಬುಕ್ಕೊ ಭೂಗೋಳ ಶಾಸ್ತ್ರೊನ್ ಕಲ್ಪಾವೊಂದಿತ್ತೆರ್<ref>{{Cite web |url=https://www.jagranjosh.com/general-knowledge/draupadi-murmu-biography-1658380804-1 |title=Draupadi Murmu Biography: Career, Family, Daughter, Husband, Education Qualification, Previous Offices and Other Details |date=2024-12-05 |accessdate=2026-05-16 |website=Jagranjosh.com |language=en}}https://www.jagranjosh.com/general-knowledge/draupadi-murmu-biography-1658380804-1</ref>. == ರಾಜಕೀಯ ವೃತ್ತಿಜೀವನ == ದ್ರೌಪದಿ ಮುರ್ಮು ರಾಯರಂಗಪುರೊಟು ಭಾರತೀಯ ಜನತಾ ಪಕ್ಷೊಗು (ಬಿಜೆಪಿ) ಸೇರಿಯೆರ್.1997 ಡ್ ಆರ್ ರಾಯರಂಗಪುರ ನಗರ ಪಂಚಾಯತ್ ಕೌನ್ಸಿಲರ್ ಆದ್ ಆಯ್ಕೆ ಆಯೆರ್.2000 ಡು ಒಡಿಶಾ ವಿಧಾನಸಭೆ ಚುನಾವಣೆಡ್ ರಾಯರಂಗ್‌ಪುರ ವಿಧಾನಸಭಾ ಕ್ಷೇತ್ರೊಡ್ದು ಗೆಂದಿಯೆರ್ ಬುಕ್ಕೊ 2000 ಬುಕ್ಕೊ 2009ದ ನಡುವೆ ಒಡಿಶಾ ವಿಧಾನಸಭೆಟ್ ರಡ್ಡ್ ಅವಧಿಡ್ ಸೇವೆ ಮಲ್ತೆರ್. [[ಒಡಿಶ]]ಡ್ ಬಿಜೆಪಿ ಬುಕ್ಕೊ ಬಿಜೆಡಿ ಸಮ್ಮಿಶ್ರ ಸರ್ಕಾರದ ಅವಧಿಡ್ ಮಾರ್ಚ್ 6, 2000 ಡ್ದ್ ಆಗಸ್ಟ್ 6, 2002 ಮುಟ್ಟ ವಾಣಿಜ್ಯ ಬುಕ್ಕೊ ಸಾರಿಗೆ ಸ್ವತಂತ್ರ ಉಸ್ತುವಾರಿ ರಾಜ್ಯ ಸಚಿವರಾದಿತ್ತೆರ್ ಬುಕ್ಕೊ [[ಆಗಸ್ಟ್]] 6, 2002 ಡ್ದ್ [[ಮೇ]] 16 2004 ಮುಟ್ಟುಅ ಮೀನುಗಾರಿಕೆ ಬುಕ್ಕೊ ಪ್ರಾಣಿ ಸಂಪನ್ಮೂಲೊದ ಅಭಿವೃದ್ಧಿ ಸಚಿವೆರಾದಿತ್ತೆರ್. 2009 ಡ್, [[ಬಿಜೆಡಿ]] ಬುಕ್ಕೊ [[ಬಿಜೆಪಿ]] ಮೈತ್ರಿ ಮುಗಿಬುಕ್ಕೊ ಆರ್ ಮಯೂರ್‌ಭಂಜ್ ಲೋಕಸಭಾ ಕ್ಷೇತ್ರೊಡ್ದು ಲೋಕಸಭೆ ಚುನಾವಣೆಡ್ ಸೋತೆರ್<ref>{{Cite web|url=https://www.prajavani.net/news/india-news/draupadi-murmu-here-are-some-little-known-facts-about-her-15th-president-of-india-politics-bjp-956363.html|title=ದೇಶದ 15ನೇ ರಾಷ್ಟ್ರಪತಿ ದ್ರೌಪದಿ ಮುರ್ಮು ಕುರಿತು ತಿಳಿಯಬೇಕಾದ ಪ್ರಮುಖ ವಿಚಾರಗಳು|first=ಪ್ರಜಾವಾಣಿ ವೆಬ್‌|last=ಡೆಸ್ಕ್‌|website=Prajavani}}</ref>. == ಜಾರ್ಖಂಡ್ ರಾಜ್ಯಪಾಲೆಯಾದ್ == ದ್ರೌಪದಿ ಮುರ್ಮು [[ಜಾರ್ಖಂಡ್‌‌]]ದ ರಾಜ್ಯಪಾಲರಾದ್ 18 ಮೇ 2015 ಡ ಪ್ರಮಾಣ ವಚನ ಸ್ವೀಕಾರ ಮಲ್ತೆರ್. ರಾಜ್ಯ ಪಾಲೆರೆನ ಪೀಠೊಡು ಕುಳ್ಳಿನ ಸುರುತ ಪೊಂಜೊವು ಪನ್ಪಿನ ಪುಗರ್ತೆ ಪಡೆಯೆರ್. ಮೆರೆನ ಆಜಿ ವರ್ಷದ ಗವರ್ನರ್ ಅಧಿಕಾರಾವಧಿ ಮೇ 2015 ಡ್ ಸುರು ಆದ್ [[ಜುಲೈ]] 2021ಡ್ ಮುಗಿಯುಂಡು. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ವ್ಯಕ್ತಿಲು]] [[ವರ್ಗೊ:ಭಾರತೊದ ರಾಷ್ಟ್ರಪತಿಲು]] 8jh3se71jochst3de32kt19zw1nva7g ಜುಲನ್ ಗೋಸ್ವಾಮಿ 0 15558 360802 307931 2026-05-16T07:39:44Z ChiK 1136 null #proveit 360802 wikitext text/x-wiki {{Infobox cricketer | name = ಜುಲನ್ ಗೋಸ್ವಾಮಿ | female = true | image = Jhulan Goswami (10 March 2009, Sydney).jpg | fullname = ಜೂಲನ್ ನಿಷಿತ್ ಗೋಸ್ವಾಮಿ | birth_date = {{Birth date and age|1982|11|25|df=yes}} | birth_place = ಚಕ್ದ, [[ಪಶ್ಚಿಮ ಬಂಗಾಳ]],ಭಾರತೋ | nickname = ಬಾಬುಲ್ | heightft = 5.5 | heightinch = 11 | batting = ಬಲಗೈ | bowling = ಬಲಗೈ | role = ಆಲ್ ರೌಂಡರ್ | country = ಭಾರತಾರತೋ | international = true | internationalspan = 2002–18 | testdebutdate = 14 ಜನವರಿ | testdebutyear = 2002 | testdebutagainst = ಇಂಗ್ಲೆಂಡ್ | testcap = 51 | lasttestdate = 16 ನವೆಂಬರ್ | lasttestyear = 2015 | lasttestagainst = ದಕ್ಷಿಣ ಆಫ್ರಿಕಾ | odidebutdate = 6 ಜನವರಿ | odidebutyear = 2002 | odidebutagainst = ಇಂಗ್ಲೆಂಡ್ | odicap = 61 | lastodidate = 6 ನವೆಂಬರ್ | lastodiyear = 2019 | lastodiagainst = ವೆಸ್ಟ್ ಇಂಡೀಸ್ | odishirt = 25 | T20Idebutdate = 5 ಆಗಸ್ಟ್ | T20Idebutyear = 2006 | T20Idebutagainst = ಇಂಗ್ಲೆಂಡ್ | T20Icap = 3 | lastT20Idate = 10 ಜೂನ್ | lastT20Iyear = 2018 | lastT20Iagainst = ಬಾಂಗ್ಲಾದೇಶ | T20Ishirt = | club1 = | year1 = | columns = 3 | column1 = [[Women's Test cricket|WTest]] | column2 = [[Women's One Day International cricket|WODI]] | column3 = [[Women's Twenty20 International|WT20I]] | matches1 = 10 | matches2 = 182 | matches3 = 68 | runs1 = 283 | runs2 = 1076 | runs3 = 405 | bat avg1 = 25.72 | bat avg2 = 14.15 | bat avg3 = 10.94 | 100s/50s1 = 0/2 | 100s/50s2 = 0/1 | 100s/50s3 = 0/0 | top score1 = 69 | top score2 = 57 | top score3 = 37[[not out|*]] | deliveries1 = 1972 | deliveries2 = 8835 | deliveries3 = 1351 | wickets1 = 40 | wickets2 = 225 | wickets3 = 56 | bowl avg1 = 16.62 | bowl avg2 = 21.48 | bowl avg3 = 21.94 | fivefor1 = 3 | fivefor2 = 2 | fivefor3 = 1 | tenfor1 = 1 | tenfor2 = 0 | tenfor3 = 0 | best bowling1 = 5/25 | best bowling2 = 6/31 | best bowling3 = 5/11 | catches/stumpings1 = 5/– | catches/stumpings2 = 64/– | catches/stumpings3 = 23/– | source = http://www.espncricinfo.com/india/content/player/53932.html ESPNcricinfo | date = 12 ಜನವರಿ 2020 }} '''ಜುಲನ್ ಗೋಸ್ವಾಮಿ''' ಭಾರತೊದ ರಾಷ್ಟ್ರೀಯೊ ಪೊಂಜೊವುಲೆನ ಕ್ರಿಕೆಟ್ ತಂಡೊ, ಬಂಗಾಳೊ ಪೊಂಜೊವುಲೆನ ತಂಡ, ಪೂರ್ವ ವಲಯೊ ಪೊಂಜೊವುಲೆನ ತಂಡ ಬುಕ್ಕೊ ಏಷ್ಯಾ ಪೊಂಜೊವುಲೆನ XI ತಂಡೊಕ್ ಗೊಬ್ಬುನ ಪೂರಾ ರೌಂಡ್ ಕ್ರಿಕೆಟರ್ ಆದುಲ್ಲೆರ್. ಫೆಬ್ರವರಿ 1, 2009 ದಾನಿ, ವಿಶ್ವ ಕಪ್ ಗಾದ್ ತಂಡೊನು ನಡಪಾರೆ ಇಂಬೆರೆನ್ ನೇಮಿಸಾಂಡ್. ತಂಡೊದ ಅವಿಭಾಜ್ಯ ಅಂಗವಾಯಿನ, ಜುಲಾನ್ ತನ್ನೊ ಬ್ಯಾಟಿಂಗ್ ಬುಕ್ಕೊ ಬೌಲಿಂಗ್ ಸಾಮರ್ಥ್ಯೊಲೆಗ್ ಪುದರ್ ಪೋತೇರ್. ಆರ್, ಟೆಸ್ಟ್ ಕ್ರಿಕೆಟ್ಡ್ 20ಡ್ದ್ ಕಡಿಮೆ ಬೌಲಿಂಗ್ ಸರಾಸರಿನ್ ಪಡೆದೆರ್. 2006-07 ದ ಸಮಯೊಡು ಸರಣಿಡ್ ಆರ್ ಇಂಗ್ಲೆಂಡ್ ಡ್ ಸುರುತ ಟೆಸ್ಟ್ ಸರಣಿದ ಗೆಲುವಿಗ್ ಭಾರತೀಯ ತಂಡೊದ ನಾಯಕತ್ವದೊ ಹೊಣೆ ಹೊರಿಯೆರ್. ಜುಲನ್, 2007ತ ಐಸಿಸಿ ಪೊಂಜೊವುಲೆನ ಆಟಗಾರೆರ್ ಪಂದ್ ಪ್ರಶಸ್ತಿನ್ ಗೆಂದಿಯೇರ್. ಆರ್, 2011ಟ್ ಅತ್ಯುತ್ತಮ ಪೊಂಜೊವುಲೆನ ಕ್ರಿಕೆಟ್ಗ್ ಎಮ್.ಎ. ಚಿದಂಬರಂ ಟ್ರೋಫಿನ್ ಪಡೆಯೆರ್. ಆರ್, ಇತ್ತೀಚೆಗ್ ಭಾರತೊದ ಪೊಂಜೊವುಲೆನ ಕ್ರಿಕೆಟ್ ತಂಡೊದ ನಾಯಕಿ ಆತುಜೆರ್. ಅಯಿತ ಜವಾಬ್ದಾರಿ ಮಿತಾಲಿ ರಾಜ್ ಆರೆನ ಮಾಡಿತ್ತು ಇತ್ತುಂಡು. ಪೊಂಜೊವುಲೆನ ಒಂಜಿ ದಿನೊತ ಕ್ರಿಕೆಟ್ದ ಇತಿಹಾಸೊಡು ಜುಲನ್ ಅತ್ಯದಿಕ ವಿಕೆಟ್ ದೈದಿನಾರ್ ಆದುಲ್ಲೆರ್ (200).<ref>{{Cite news |url=https://timesofindia.indiatimes.com/sports/cricket/news/jhulan-goswami-becomes-the-leading-wicket-taker-in-womens-odis/articleshow/58594182.cms |title=Jhulan Goswami becomes the leading wicket-taker in Women’s ODIs |date=2017-05-09 |work=The Times of India |access-date=2026-05-16 |issn=0971-8257}}https://timesofindia.indiatimes.com/sports/cricket/news/jhulan-goswami-becomes-the-leading-wicket-taker-in-womens-odis/articleshow/58594182.cms</ref><ref>{{Cite news |url=https://timesofindia.indiatimes.com/sports/cricket/news/goswami-breaks-record-as-indian-women-beat-sa-women-by-7-wkts/articleshow/58597945.cms |title=Goswami breaks record as Indian women beat SA women by 7 wkts |date=2017-05-09 |work=The Times of India |access-date=2026-05-16 |issn=0971-8257}}https://timesofindia.indiatimes.com/sports/cricket/news/goswami-breaks-record-as-indian-women-beat-sa-women-by-7-wkts/articleshow/58597945.cms</ref><ref>{{Cite news |url=https://www.thehindu.com/sport/cricket/jhulan-goswami-is-the-highest-wicket-taker-in-womens-one-day-internationals/article18414380.ece |title=Jhulan Goswami is highest wicket-taker in women’s ODIs |last=Desk |first=The Hindu Net |date=2017-05-09 |work=The Hindu |access-date=2026-05-16 |language=en-IN |issn=0971-751X}}https://www.thehindu.com/sport/cricket/jhulan-goswami-is-the-highest-wicket-taker-in-womens-one-day-internationals/article18414380.ece</ref> ಕ್ಯಾಥರಿನ್ ಫಿಟ್ಜ್ಪ್ಯಾಟ್ರಿಕ್ ಆರ್ ನಿವೃತ್ತಿ ಆಯಿ ಬುಕ್ಕೊ ವಿಶ್ವ ಪೊಂಜೊವುಲೆನ ಕ್ರಿಕೆಟ್ ಡ್ ಅತಿ ವೇಗೊದ ಬೌಲರ್ ಆದುಲ್ಲೆರ್.<ref name="rediff.com">{{Cite web |url=https://www.rediff.com/cricket/special/jhulan/20060930.htm |title=How Jhulan became the world's fastest bowler |accessdate=2026-05-16 |website=Rediff |last=Kotian |first=Harish |language=en}}</ref> ಕ್ಯಾಥರಿನ್ ಫಿಟ್ಜ್ಪ್ಯಾಟ್ರಿಕ್ ಆರ್ ನಿವೃತ್ತಿ ಆಯಿ ಬುಕ್ಕೊ ವಿಶ್ವ ಪೊಂಜೊವುಲೆನ ಕ್ರಿಕೆಟ್ ಡ್ ಅತಿ ವೇಗೊದ ಬೌಲರ್ ಆದುಲ್ಲೆರ್.<ref name="rediff.com"/> ಕ್ಯಾಥರಿನ್ ಫಿಟ್ಜ್ಪ್ಯಾಟ್ರಿಕ್ ಆರ್ ನಿವೃತ್ತಿ ಆಯಿ ಬುಕ್ಕೊ ವಿಶ್ವ ಪೊಂಜೊವುಲೆನ ಕ್ರಿಕೆಟ್ ಡ್ ಅತಿ ವೇಗೊದ ಬೌಲರ್ ಆದುಲ್ಲೆರ್.<ref name="rediff.com"/> ಫೆಬ್ರವರಿ 2015ಟ್, ದಕ್ಷಿಣ ಆಫ್ರಿಕಾ ವಿರುದ್ಧದ ಪಂದ್ಯೊಡು 2೦೦ ವಿಕೆಟ್ ಲೆನ್ ಪಡೆಯಿನ ಸುರುತ ಬೌಲರ್ ಆದ್ ಉಲ್ಲೆರ್. ದಕ್ಷಿಣ ಆಫ್ರಿಕೊದ ಆರಂಭಿಕ ಲಾರಾ ವೊಲ್ವಾರ್ಡ್ಟ್ ವಿಕೆಟ್ ಪಡೆನಗ, ಈ ಸಾಧನೆ ಮಂತ್ ಇತ್ತೆರ್. == ಬಾಲ್ಯೊ == ಜುಲಾನ್ ಗೋಸ್ವಾಮಿ ಪಶ್ಚಿಮ ಬಂಗಾಳೊದ ನಾಡಿಯಾ ಜಿಲ್ಲೆಡ್, 25 ನವೆಂಬರ್ 1982ಡ್ ಪುಟ್ಟಿಯೆರ್. ಆರ್ ಪಶ್ಚಿಮ ಬಂಗಾಳೊದ, ನಾಡಿಯೊಡು ಕಿನ್ಯ ಪಟ್ಟಣವಾಯಿನ ಚಕ್ಧಾಹಡ್,ಮಧ್ಯಮವರ್ಗೊದ ಕುಟುಂಬೊಗ್ ಸೇರ್ದೆರ್. ಆರೆಗ್ 15 ವರ್ಷ ಉಪ್ಪುನಗ ಕ್ರಿಕೆಟ್ ಗೊಬ್ಬರೆ ಪ್ರಾರಂಭ ಮಂತೆರ್. ಕ್ರಿಕೆಟ್ ಪ್ರಾರಂಭ ಮನ್ಪುನ ದುಂಬು, ಆರ್ ಫುಟ್ಬಾಲ್ದ ಅಭಿಮಾನಿ ಆದು ಇತ್ತೆರ್.ಅರೆಗ್, ಕ್ರಿಕೆಟ್ ಆಟೊದ ಅರಿವಾಯಿನಿ, 1992 ದ ಕ್ರಿಕೆಟ್ ವಿಶ್ವಕಪ್ ಟಿವಿಡ್ ತೂನಗ. ಅಂಚಾ, ಅರೆನ ಕ್ರಿಕೆಟ್ ಪ್ರೇಮ ಬುಲೆಂಡು. ಆಂಡಾ, ಭಾರತೊದ ಬೆಲೆ, ಪೋಷಕ ಜುಲಾನ ಅರೆನ ಪೊಪ್ಪ ಅಮ್ಮ ಕ್ರಿಕೆಟ್ ದ ಬದಲು ಅಧ್ಯಯೊನದ ಬಗ್ಗೆ ಗಮನ ಕೊರ್ರೆ ಪನೊಂದು ಇತ್ತೆರ್. ಆಂಡಾ ಜುಲಾನ್ ಕ್ರಿಕೆಟ್ ನ್ ಉಂತಾಯಿಜೆರ್. ಕ್ರಿಕೆಟ್ದ ಮಿತ್ತು ಅರೆನ ಮೋಕೆ ಮಸ್ತ್ ಜಾಸ್ತಿ ಆಂಡ್ ಪಂದ್ ಅಕಲೆಗ್ ಗೊತ್ತಾನಗ ಅಕುಲು ಅರೆನ್, ಕ್ರಿಕೆಟ್ ತರಬೇತಿಗಾದ್ ಕೆಲವು ಕ್ರಮೊಲೆನ್ ತೆತ್ತೊಂಡೆರ್. ಆ ಸಮಯೊಡು ಅರೆನ ಅಪ್ಪೆ ಇಲ್ಲಡ್ ಒವ್ವೆ ಕ್ರಿಕೆಟ್ ಸೌಲಭ್ಯಲೆನ್ ಹೊಂದುದುಜೆರ್, ಅಂಚಾ ಆರ್ ಕೊಲ್ಕತ್ತಾಗ್ ಪೋಯೆರ್. ಅರೆನ ಶಿಕ್ಷಣೊ ಬುಕ್ಕೊ ಕ್ರಿಕೆಟ್ ರಡ್ಡೆತಲ ವೇಳಾಪಟ್ಟಿ ಮಂತುದು, ಬಾರೀ ಭಂಗೊಡು ತನ್ನ ಕಠಿಣ ಕೆಲಸೊನುಲ ಅಯಿತೊಟ್ಟು ಕ್ರಿಕೆಟ್ ತರಭೇತಿಲಾ ಮುಂದುವರಿಸಾಯೆರ್.<ref name="espncricinfo.com"/> == ವೃತ್ತಿ ಜೀವನೊ == ತನ್ನ ಕಿನ್ಯ ಪ್ರಾಯೊಡ್ದುಲಾ ಆರ್ ಕ್ರಿಕೆಟ್ ಗಾದ್ ಮಸ್ತ್ ಕಷ್ಟ ಬತ್ತುದು ಕೆಲಸ ಮಂತೆರ್. ಕೋಲ್ಕತೊಡು ಆರ್ ಅರೆನ ಕ್ರಿಕೆಟ್ ತರಬೇತಿ ಪಡೆಯೆರ್. ಶೀಘ್ರೊಡೇ ಆರ್ ಬಂಗಾಳೊ ಕ್ರಿಕೆಟ್ ತಂಡೊಡು ಪ್ರವೇಶೊ ಮಂತೆರ್. ಅರೆನ 19ನೇ ವರ್ಷೊಡೇ, ಚೆನ್ನೈಡ್ ಇಂಗ್ಲೆಂಡ್ದ ವಿರೋಧ ಒಂಜಿ ದಿನೊತ ಅಂತಾರಾಷ್ಟ್ರೀಯ ಪಂದ್ಯೊ ಒಂಜೇಟ್ ಆರ್ ಭಾರತೊ ದೇಶೊನು ಪ್ರತಿನಿದಿಸಾಯೇರ್. ಆರ್ ಅಂತರರಾಷ್ಟ್ರೀಯೊ ಟೆಸ್ಟ್ ಪಂದ್ಯಗ್ ಪಾದಾರ್ಪಣೆ ಮಂದಿನಿ 2002, ಜನವರಿ 14 ಟ್ ಇಂಗ್ಲೆಂಡ್ದ ವಿರುದ್ಧ ಲಕ್ನೋಡ್ ನಡೆತುಂಡು ಬುಕ್ಕೊ ಅರೆನ ಟ್ವೆಂಟಿ -20 ಪಾದರ್ಪಣ ಪಂದ್ಯ 2006ಟ್ ಡರ್ಬಿಡ್ ನಡೆತುಂಡು.2006,-2007ಟ್ ಕ್ರೀಡಾಋತುಡು, ಗೋಸ್ವಾಮಿ ಮಿಥಾಲಿ ರಾಜ್ ನ ಒಟ್ಟುಗು ಭಾರತದ ಪೊಂಜೋವುಲೆನ ಕ್ರಿಕೆಟ್ ತಂಡೊನು ದುಂಬು ಕಂತುದು, ಇಂಗ್ಲೆಂಡ್ದ ವಿರುದ್ದ ಸುರುತ ಟೆಸ್ಟ್ ಸರಣಿ ಗೆಂದಿಯೆರ್.2007ಟ್ ಭಾರತೊಡು ನಡೆಯಿನ, ಆಫ್ರೋ ಏಷ್ಯಾನ್ ಪಂದ್ಯಾವಳಿಡ್ ಏಷ್ಯಾ ತಂಡೊಡು ಜುಲಾನ್ ಒರ್ತಿ ಆದು ಇತ್ತೆರ್. "ಐಸಿಸಿ ಪೊಂಜೋವುಲೆನ ಕ್ರಿಕೆಟರ್ ಆಫ್ ದಿ ಇಯರ್" ಪ್ರಶಸ್ತಿ ಲಾ ಮೆರೆನ ಪಾಲಾತುಂಡು.2008 ಟ್ ಆರ್, ಮಿಥಾಲಿ ರಾಜ್ ಅರೆಡ್ದ್ ನಾಯಕತ್ವೊನು ವಹಿಸಾಯೆರ್ ಬುಕ್ಕೊ 2011 ಮುಟ್ಟ ಆ ನಾಯಕತ್ವೊನು ಮುಂದುಸಾಯೆರ್. 2008ಟ್, ಆರ್ ಏಷ್ಯಾ ಕಪ್ ಡ್, ಒಂಜಿ ದಿನೊತ ಪಂದ್ಯೊಡು 100 ವಿಕೆಟ್ ಲೆನ್ ಪಡೆಯಿನ ನಾಲನೇ ತ ಪೊಂಜೋವು ಪನ್ಪಿನ ಪ್ರಶಂಸೆಗ್ ಪಾತ್ರರಾತೆರ್. ಆರ್ 25 ಒಂಜಿ ದಿನ ಪಂದ್ಯೊಡು ಭಾರತೊನು ದುಂಬು ಕೊಂಡೆರ್. 2010ಟ್ ಆರ್ "ಅರ್ಜುನ ಪ್ರಶಸ್ತಿನ್ " ಪಡೆಯೆರ್ ಬುಕ್ಕೊ 2012 ಟ್ 2012ಟ್ ಡಯಾನಾ ಎಡ್ಲ್ಜಿ ಅರೆನ ಬುಕ್ಕೊ "ಪದ್ಮಶ್ರೀ ಪ್ರಶಸ್ತಿ" ಸ್ವೀಕರಿಸಿನ ರಡ್ಡನೇ ಭಾರತೊದ ಪೊಂಜೋವು ಕ್ರಿಕೆಟಿಗರಾಯೆರ್.ಆರ್ 10 ಟೆಸ್ಟ್ ಪಂದ್ಯೊಡು 40 ವಿಕೆಟ್ ಲೆನ್ ಪಡೆದೆರ್. ಒಟ್ಟು 223 ಪಂದ್ಯೊಲೆಡ್ ಆರ್ 271 ಅಂತಾರಾಷ್ಟ್ರೀಯಯಯೊ ವಿಕೆಟ್ ಲೆನ್ ದೇಯಿದೆರ್ ಬುಕ್ಕೊ ಮೂಜಿ ಅರ್ದ ಶತಕದೊ ಒಟ್ಟುಗು 1593 ರನ್ ಲೆನ್ ಗಳಿಸಾದೆರ್. ಆಸ್ಟ್ರೇಲಿಯೊದ, ಕ್ಯಾಥರಿನ್ ಫಿಟ್ಜ್ಪ್ಯಾಟ್ರಿಕ್ನ 180 ಒಂಜಿ ದಿನೊತ ವಿಕೆಟ್ಲೆನ ದಾಖಲೆನ್ ದಾಟುದು, ಮೇರ್ ಜಾಸ್ತಿ ವಿಕೆಟ್ ದೆತ್ತೊಂದೆರ್. ಆರ್ 60, ಟಿ-20 ಅಂತರರಾಷ್ಟ್ರೀಯೊ ಪಂದ್ಯೊಲೆಡ್ 50 ವಿಕೆಟ್ ಲೆನ್ ದೆತ್ತೊಂದೆರ್.2017 ಟ್ ಪೊಂಜೋವುಲೆನ ಕ್ರಿಕೆಟ್ ವಿಶ್ವಕಪ್ ಫೈನಲ್ ತಲುಪಿನ ಭಾರತೊದ ತಂಡೊಡು ಗೋಸ್ವಾಮಿ ಭಾಗಿ ಆತೇರ್.<ref>{{Cite web |url=https://www.hindustantimes.com/cricket/why-women-s-cricket-world-cup-final-is-extra-special-for-mithali-raj-jhulan-goswami/story-RZvrp01lhhm3uN634vZ65N.html |title=Why Women’s Cricket World Cup final is extra special for Mithali Raj, Jhulan Goswami |date=2017-07-22 |accessdate=2026-05-16 |website=Hindustan Times |last=Anonymous |language=en}}https://www.hindustantimes.com/cricket/why-women-s-cricket-world-cup-final-is-extra-special-for-mithali-raj-jhulan-goswami/story-RZvrp01lhhm3uN634vZ65N.html</ref><ref>"How England won Women's World Cup – clips & reaction". BBC Sport. Retrieved 19 March 2020.</ref> ಆರ್ ಭಾರತೊದ ಪೊಂಜೊವುಲೆನ ರಾಷ್ಟ್ರೀಯ ಕ್ರಿಕೆಟ್ ತಂಡೊದ ಬೌಲಿಂಗ್ ಸಲಹೆಗಾರರಾದ್ ನೇಮಕ ಆಯೇರ್. ಆರ್ ಆಟಗಾರ-ತರಬೇತುದಾರರಾದ್ ಕೆಲಸ ನಿರ್ವಹಣೆ ಮಂದೆರ್. == ಪ್ರಶಸ್ತಿಲು, ಗೌರವೊಲು == * 2007 - ವರ್ಷೊದ ಐಸಿಸಿ ಮಹಿಳಾ ಕ್ರಿಕೆಟರ್ * ಭಾರತೊದ ಪೊಂಜೋವುಲೆನ ಕ್ರಿಕೆಟ್ ತಂಡೊದ ನಾಯಕಿ (2008–2011)-ವೇಗೊದ ಬೌಲರ್ * 2010 - ಅರ್ಜುನ ಪ್ರಶಸ್ತಿ * 2012 - ಪದ್ಮ ಶ್ರೀ ಪ್ರಶಸ್ತಿ * ಮಸ್ತ್ ಜಾಸ್ತಿ ಅಂತಾರಾಷ್ಟ್ರೀಯ ವಿಕೆಟ್ ಪಡೆಯಿನ ಭಾರತೊದ ಆಟಗಾರ್ತಿ == ಉಲ್ಲೇಕೊ == [[ವರ್ಗೊ:ಪೊಂಜೊವುಲು]] 7bxkrqyddw6yclf5q11yr9tzdv3qym4 ಆಟಿಕುಲ್ಲುನೆ 0 16085 360725 280570 2026-05-16T07:23:39Z ChiK 1136 null #proveit 360725 wikitext text/x-wiki '''ಆಟಿದ ಕುಲ್ಲುನೆ''' ಸೌರಮಾನೊದ ನಾಲೆನೆ ತಿಂಗೊಲು [[ಆಟಿ]]ಡ್ ಈ ಕ್ರಮ ಆಚರಣೆಡ್ ಉಂಡು. ಉತ್ತರಾಯನೊ ಕರಿದ್ ದಕ್ಷಿಣಾಯನೊದ ಈ ಆಟಿ ತಿಂಗೊಲುಡು ಕೀರಿಕುಟ್ಟ್‌ದ ಬರ್ಪುಂಡು. ಈ ಬರ್ಸೊಗು [[ಭೂಮಿ]] ಪೂರಾ ಪರ್ಂದ್‌ದ್ ಪೋಪುಂಡು. ಆಟಿಡ್ [[ಭೂಮಿ]] ಸೀತೊ ಏರ್ದಿಪ್ಪುಂಡು. ಇಂದೆಕಾತ್ರೊ ಒಂಜಾತ್ ನಿಸೇದೊ, ಆಟಿಕುಲ್ಲುನೆದ ಪುದರ್ಡ್ ಆಟಿಡ್ ಇಸೇಸೊಡ್ ಆಪುಂಡು.<ref>{{Cite news |url=http://vijaykarnataka.indiatimes.com/lavalavk/culture/-/articleshow/15235460.cms |title=ತುಳುನಾಡಿನ ವಿಶಿಷ್ಟ ಆಚರಣೆ ಆಟಿ ಕಳೆಂಜ - Vijaykarnataka |date=2012-07-29 |work=Vijaykarnataka |access-date=2026-05-16 |language=kn}}http://vijaykarnataka.indiatimes.com/lavalavk/culture/-/articleshow/15235460.cms</ref> === ಆಟಿ ಕುಲ್ಯರ ಲೆತೊಂದು ಪೋಪುನೆ === ಪೊಸ ಮದಿಮ್ಮಾಲೆ ಸುರತ್ತ ಆಟಿಗ್ ಅಪ್ಪೆ ಇಲ್ಲಡೆಗ್ ಅಪ್ಪೆ ಇಲ್ಲ್ದಕ್ಲ್ ಪೋದು ಲೆತ್ತೊಂದು ಬರ್ಪುನ ಕ್ರಮ. ಮದಿಮ್ಮಾಲೆನ್ ದಾಯೆ ಇಲ್ಲಡೆ ಲೆತೊಂದು ಬರ್ಪುನೆ? ಆಟಿಕುಲ್ಲುನೆಂದ್ ದಾಯೆ ಪನ್ಪೆರ್? ಇಂಚಪೂರ ಪ್ರಶ‍್ನೆಲು ಲಕ್ಕುವೊ. == ಆಟಿ ಸಮ್ಮನೊ == ಆಟಿ ಕುಲ್ಯರ ಬತ್ತ್‌ನ ಮಗಳೆನ್ ಕಂಡಾನಿ ಇಲ್ಲಡೆ ಲೆತೊಂದ್ ಪೋಪುನ ಕ್ರಮೊ ಉಂಡು. ಅಪಗ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡುಂದು ಪನ್ಪೆರ್. ಕಬಿತಡ್ ಇಂಚೊಂಜಿ ಪಾತೆರೊ ಉಂಡು, '''ಬರಾಂದಿ ಬಿನ್ನೆರ್ ಬತ್ತೆರ್ ಮಗ ಸೇಸೊ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡಾಂಡೆ'''. === ಆಟಿದ ನಂಬಿಕೆಲು === ಆಟಿಡ್ ಪೊಣ್ಣು [[ಬಾಲೆ]] [[ಮದಿಮಾಳ್ ಮದಿಮೆ|ಮದಿಮಾಲ್]] ಆಂಡ ಅನಿಷ್ಠ ಪನ್ಪಿ ನಂಬೊಲಿಕೆ ಉಂಡು. ಆಟಿಡ್ ಮದಿಮಲಾಯಿನ ಪೊಣ್ಣಗ್, ಸೀಕ್‌ದ ಜೋಕುಲೆಗ್, ಗೊಡ್ಡು ಪೆತ್ತಗ್, ಫಲಕೊರಂದಿ ತಾರೆಗ್ ಬುಕ್ಕೊ ಸಂತತಿ ಆವಂದಿ ಪೊಂಜೋವುಲೆಗ್ ಆಟಿ ಕಳೆಂಜಡ ತರೆಕ್ಕ್ ನೀರ್ ಮೈಪದ್ ಕಳೆಂಜಗ್ ದಾನೊ ಕೊರ್ಂಡ ಆ ಅನಿಷ್ಠ ಕಳೆಯುಂಡು, ಜೋಕುಲಾಪುಂಡು ಪಲ ದಿಂಜಿದ್ ಉರ್ಕರುಂಡು ಪನ್ಪಿ ನಂಬಿಕೆಲ ತುಳುನಾಡ್‌ಡ್ ಆಟಿಕಳೆಂಜ ಪಾಡ್ದಾನೊಡು ಬರ್ಪುಂಡು. === ಆಟಿದ ಗಾದೆಲು === # ಆಟಿಡ್ ಪೆದ್ದುನ ಬಾಲೆ ಪೊಣ್ಣು # ಆಟಿಡ್ ಕಂಡನಿ ಬುಡೆದಿ ಒಟ್ಟೂಗೆ ಇಪ್ಪರೆ ಆವಂದ್ === ಆಟಿದ ಕತ್ತಲೆ === ಆಟಿದ ಸಮಯೊಡು ಮಿನ್ಪುರಿ ಬರ್ಪುಂಡು. ಕರೆಂಟ್ ಇದ್ಯಾಂದಿ ಇಲ್ಲ್ದ ಸುತ್ತುಡೆ ಮಿನ್ಪರಿದ ಬೊಲ್ಪು ಅಪಾಪಗ ಮಿಂಚುಂಡು. ಅಯಿತ ನಡುಟ್ ಕರ್ಗುಡ ಕತ್ತಲೆ ಬರ್ಪುಂಡು. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ಜಾನಪದ]] [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] 8za43gujyq5qa03lnky4rusext8xuon 360804 360725 2026-05-16T09:32:09Z ChiK 1136 Added {{[[Template:Merge to|Merge to]]}} tag 360804 wikitext text/x-wiki {{Merge to|ಆಟಿ ಕುಲ್ಲುನು|discuss=Talk:ಆಟಿ ಕುಲ್ಲುನು#Proposed merge of ಆಟಿಕುಲ್ಲುನೆ into ಆಟಿ ಕುಲ್ಲುನು|date=ಮೇ ೨೦೨೬}} '''ಆಟಿದ ಕುಲ್ಲುನೆ''' ಸೌರಮಾನೊದ ನಾಲೆನೆ ತಿಂಗೊಲು [[ಆಟಿ]]ಡ್ ಈ ಕ್ರಮ ಆಚರಣೆಡ್ ಉಂಡು. ಉತ್ತರಾಯನೊ ಕರಿದ್ ದಕ್ಷಿಣಾಯನೊದ ಈ ಆಟಿ ತಿಂಗೊಲುಡು ಕೀರಿಕುಟ್ಟ್‌ದ ಬರ್ಪುಂಡು. ಈ ಬರ್ಸೊಗು [[ಭೂಮಿ]] ಪೂರಾ ಪರ್ಂದ್‌ದ್ ಪೋಪುಂಡು. ಆಟಿಡ್ [[ಭೂಮಿ]] ಸೀತೊ ಏರ್ದಿಪ್ಪುಂಡು. ಇಂದೆಕಾತ್ರೊ ಒಂಜಾತ್ ನಿಸೇದೊ, ಆಟಿಕುಲ್ಲುನೆದ ಪುದರ್ಡ್ ಆಟಿಡ್ ಇಸೇಸೊಡ್ ಆಪುಂಡು.<ref>{{Cite news |url=http://vijaykarnataka.indiatimes.com/lavalavk/culture/-/articleshow/15235460.cms |title=ತುಳುನಾಡಿನ ವಿಶಿಷ್ಟ ಆಚರಣೆ ಆಟಿ ಕಳೆಂಜ - Vijaykarnataka |date=2012-07-29 |work=Vijaykarnataka |access-date=2026-05-16 |language=kn}}http://vijaykarnataka.indiatimes.com/lavalavk/culture/-/articleshow/15235460.cms</ref> === ಆಟಿ ಕುಲ್ಯರ ಲೆತೊಂದು ಪೋಪುನೆ === ಪೊಸ ಮದಿಮ್ಮಾಲೆ ಸುರತ್ತ ಆಟಿಗ್ ಅಪ್ಪೆ ಇಲ್ಲಡೆಗ್ ಅಪ್ಪೆ ಇಲ್ಲ್ದಕ್ಲ್ ಪೋದು ಲೆತ್ತೊಂದು ಬರ್ಪುನ ಕ್ರಮ. ಮದಿಮ್ಮಾಲೆನ್ ದಾಯೆ ಇಲ್ಲಡೆ ಲೆತೊಂದು ಬರ್ಪುನೆ? ಆಟಿಕುಲ್ಲುನೆಂದ್ ದಾಯೆ ಪನ್ಪೆರ್? ಇಂಚಪೂರ ಪ್ರಶ‍್ನೆಲು ಲಕ್ಕುವೊ. == ಆಟಿ ಸಮ್ಮನೊ == ಆಟಿ ಕುಲ್ಯರ ಬತ್ತ್‌ನ ಮಗಳೆನ್ ಕಂಡಾನಿ ಇಲ್ಲಡೆ ಲೆತೊಂದ್ ಪೋಪುನ ಕ್ರಮೊ ಉಂಡು. ಅಪಗ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡುಂದು ಪನ್ಪೆರ್. ಕಬಿತಡ್ ಇಂಚೊಂಜಿ ಪಾತೆರೊ ಉಂಡು, '''ಬರಾಂದಿ ಬಿನ್ನೆರ್ ಬತ್ತೆರ್ ಮಗ ಸೇಸೊ ಕೊರಾಂದಿ ಸಮ್ಮನೊ ಕೊರೊಡಾಂಡೆ'''. === ಆಟಿದ ನಂಬಿಕೆಲು === ಆಟಿಡ್ ಪೊಣ್ಣು [[ಬಾಲೆ]] [[ಮದಿಮಾಳ್ ಮದಿಮೆ|ಮದಿಮಾಲ್]] ಆಂಡ ಅನಿಷ್ಠ ಪನ್ಪಿ ನಂಬೊಲಿಕೆ ಉಂಡು. ಆಟಿಡ್ ಮದಿಮಲಾಯಿನ ಪೊಣ್ಣಗ್, ಸೀಕ್‌ದ ಜೋಕುಲೆಗ್, ಗೊಡ್ಡು ಪೆತ್ತಗ್, ಫಲಕೊರಂದಿ ತಾರೆಗ್ ಬುಕ್ಕೊ ಸಂತತಿ ಆವಂದಿ ಪೊಂಜೋವುಲೆಗ್ ಆಟಿ ಕಳೆಂಜಡ ತರೆಕ್ಕ್ ನೀರ್ ಮೈಪದ್ ಕಳೆಂಜಗ್ ದಾನೊ ಕೊರ್ಂಡ ಆ ಅನಿಷ್ಠ ಕಳೆಯುಂಡು, ಜೋಕುಲಾಪುಂಡು ಪಲ ದಿಂಜಿದ್ ಉರ್ಕರುಂಡು ಪನ್ಪಿ ನಂಬಿಕೆಲ ತುಳುನಾಡ್‌ಡ್ ಆಟಿಕಳೆಂಜ ಪಾಡ್ದಾನೊಡು ಬರ್ಪುಂಡು. === ಆಟಿದ ಗಾದೆಲು === # ಆಟಿಡ್ ಪೆದ್ದುನ ಬಾಲೆ ಪೊಣ್ಣು # ಆಟಿಡ್ ಕಂಡನಿ ಬುಡೆದಿ ಒಟ್ಟೂಗೆ ಇಪ್ಪರೆ ಆವಂದ್ === ಆಟಿದ ಕತ್ತಲೆ === ಆಟಿದ ಸಮಯೊಡು ಮಿನ್ಪುರಿ ಬರ್ಪುಂಡು. ಕರೆಂಟ್ ಇದ್ಯಾಂದಿ ಇಲ್ಲ್ದ ಸುತ್ತುಡೆ ಮಿನ್ಪರಿದ ಬೊಲ್ಪು ಅಪಾಪಗ ಮಿಂಚುಂಡು. ಅಯಿತ ನಡುಟ್ ಕರ್ಗುಡ ಕತ್ತಲೆ ಬರ್ಪುಂಡು. == ಉಲ್ಲೇಕೊಲು == {{Reflist}} [[ವರ್ಗೊ:ತುಳು ಜಾನಪದ]] [[ವರ್ಗೊ:ತುಳು ತಿಂಗೊಲು]] l97jx4cddxe5029z014y7klfstt0fqw ಪಾತೆರ:ಆಟಿ ಕುಲ್ಲುನು 1 16592 360805 176672 2026-05-16T09:32:11Z ChiK 1136 /* Proposed merge of ಆಟಿಕುಲ್ಲುನೆ into ಆಟಿ ಕುಲ್ಲುನು */ಪೊಸ ವಿಭಾಗ 360805 wikitext text/x-wiki {{ತುಳುವೆರೆ ಆಟಿ ತಿಂಗೊಲುದ ಲೆಕನೊ}} == Proposed merge of [[ಆಟಿಕುಲ್ಲುನೆ]] into [[ಆಟಿ ಕುಲ್ಲುನು]] == Only the title will be differ the matter is same. [[ಬಳಕೆದಾರೆ:ChiK|ChiK]] ([[ಬಳಕೆದಾರೆ ಪಾತೆರ:ChiK|ಪಾತೆರ್ಲೆ]]) ೧೫:೦೨, ೧೬ ಮೇ ೨೦೨೬ (IST) k112x71gldkdw7z108m62o4zdo6jmc9 ವಿಕಿಪೀಡಿಯ:ಫೈಲ್ ಅಪ್‌ಲೋಡ್ ವಿಝಾರ್ಡ್ 4 22077 360803 337031 2026-05-16T09:22:35Z ChiK 1136 360803 wikitext text/x-wiki <noinclude>__NOTOC__ __NOEDITSECTION__</noinclude><div id="fuwStartScriptLink" class="plainlinks">ವಿಕಿಪೀಡಿಯಡು ಉಪಯೋಗ ಮಲ್ಪರೆ ಒಂಜಿ ಚಿತ್ರ ಅತ್ತಂಡ ಬೇತೆ ಮಾಧ್ಯಮ ಕಡತೊನು ಕೊರೊಡು ಪನ್ಪಿನೆಕ್ ಸೊಲ್ಮೆಲು. ಈ ವಿಝಾರ್ಡ್ ನಿಕುಲೆಗ್ ಒಂಜಿ ಪ್ರಶ್ನಾವಳಿದ ಮೂಲಕ ಮಾರ್ಗದರ್ಶನ ಕೊರ್ಪುಂಡು, ಉಂದು ನಿಕುಲೆಗ್ ಪ್ರತಿಯೊಂಜಿ ಫೈಲ್‌ಗ್ ಸೂಕ್ತವಾದ್ ಕೃತಿಸ್ವಾಮ್ಯ ಬೊಕ್ಕ ಮೂಲ ಮಾಹಿತಿನ್ ಕೇನುಂಡು. ಮುಂದುವರಿಯುನ ದುಂಬು ಈರ್ ಕೃತಿಸ್ವಾಮ್ಯ ಬೊಕ್ಕ ಚಿತ್ರೊದ ಬಳಕೆದ ನೀತಿನ್ ಅರ್ಥ ಮಲ್ತೊಂದುಲ್ಲರ್ ಪನ್ಪಿನೆನ್ ಖಚಿತ್ ಮಲ್ಪುಲೆ. <div style="text-align:center;">{{Clickable button 2|commons:Special:UploadWizard|ನಿಕ್ಲೆನ ಸ್ವಂತ ಅತ್ತ್ಂಡ ಮುಕ್ತವಾದ್ ಪರವಾನಗೆ ಇಪ್ಪುನ ಫೈಲ್‌ನ್ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುಲೆ|class=mw-ui-progressive|style=border-radius:4px; font-size:1.5em;}} [[ವಿಕಿಪೀಡಿಯ:ವಿಕಿಮೀಡಿಯಾ ಕಾಮನ್ಸ್|ವಿಕಿಮೀಡಿಯಾ ಕಾಮನ್ಸ್]] ಗ್ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುನಕುಲು. {{break}} <div class="nomobile"> {{Clickable button 2|ಒಂಜಿ ಉಚಿತ ಅತ್ತಂದ್‌ನ ಫೈಲ್‌ನ್ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುಲೆ|url={{fullurl:{{FULLPAGENAME}}|withJS=MediaWiki:FileUploadWizard.js&withCSS=MediaWiki:FileUploadWizard.css}}|style=border-radius:4px; font-size:1.5em; color:var(--color-progressive, #36c);}} ತುಳು ವಿಕಿಪೀಡಿಯೊಗು ಸ್ಥಳೀಯವಾದ್ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುನವು; [[ವಿಕಿಪೀಡಿಯ:ದರ್ಮೊದ ಅತ್ತಂದ್‌ನ ವಿಸಯೊ|ದರ್ಮೊದ ಅತ್ತಂದ್‌ನ ವಿಸಯೊ]] ಮಾನದಂಡೊಲೆನ್ ಪಾಲನೆ ಮಲ್ಪೊಡು </div> </div> </div> {{noscript|1= <div id="warningNoJavaScript" class="uploadWarning"> '''You do not have JavaScript enabled''' Sorry, in order to use this uploading script, JavaScript must be enabled. You can still use the plain [[Special:Upload]] page to upload files to the Tulu Wikipedia without JavaScript. </div> }} <div id="warningLoggedOut" class="uploadWarning" style="display:none;"> '''You are not currently logged in.''' Sorry, in order to use this uploading script and to upload files, you need to be logged in with your named account. Please '''<span class="plainlinks">[{{fullurl:Special:UserLogin|returnto=ವಿಕಿಪೀಡಿಯ%3Aಫೈಲ್+ಅಪ್%E2%80%8Cಲೋಡ್+ವಿಝಾರ್&returntoquery=withJS%3DMediaWiki%253AFileUploadWizard.js}} log in]</span>''' and then try again. </div> <div id="warningNotConfirmed" class="uploadWarning" style="display:none;"> '''Your account has not become confirmed yet.''' Sorry, in order to upload files on the Tulu Wikipedia, you need to have a [[WP:AUTOCONFIRM|confirmed account]]. Normally, your account will become confirmed automatically once you have made 10 edits and four days have passed since you created it. You may already be able to upload files on the [[:commons:|Wikimedia Commons]], but you can't do it on the Tulu Wikipedia just yet. If the file you want to upload has a free license, please go to Commons and upload it there. '''Important note:''' if you don't want to wait until you are autoconfirmed, you may ask somebody else to upload a file for you at [[Wikipedia:Files for upload]]. <small>In very rare cases an administrator may make your account confirmed manually through a request at [[Wikipedia:Requests for permissions/Confirmed]].</small> </div> <div id="UploadScriptArea" style="display:none;"> <div id="placeholderTargetForm" class="uploadScriptSection"> ==ಸ್ಟೆಪ್ ೧: ನಿಕ್ಲೆನ ಫೈಲ್‍ನ್ ಆಯ್ಕೆ ಮಲ್ಪುಲೆ== {| |- |class="uwLegend"|<span class="uwObligatory">File:</span> |<span id="placeholderfile"></span><br/><small>Choose a file from your computer. Maximum file size: 100 MB.<br/>Permitted file types: png, gif, jpg, jpeg, xcf, pdf, mid, mp3, mpeg, mpg, ogg, ogv, opus, svg, djvu, tiff, tif, oga, flac, wav, wave, webm, webp.</small> <span id="placeholderapiAction"></span> <span id="placeholderapiFormat"></span> <span id="placeholderapiFilename"></span> <span id="placeholderapiText"></span> <span id="placeholderapiComment"></span> <span id="placeholderapiToken"></span> <span id="placeholderapiIgnorewarnings"></span> <span id="placeholderapiWatch"></span> <span id="placeholderTargetIFrame"></span> |- |} </div> <div id="placeholderScriptForm"> <div id="UploadScriptStep1" class="uploadScriptSection"> ==ಸ್ಟೆಪ್ ೨: ನಿಕ್ಲೆನ ಫೈಲ್‍ನ್ ವಿವರಿಸಲೆ== {| |- |colspan="2"|Please provide a clear, descriptive name by which your file will be known on Wikipedia. |- |class="uwLegend"|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderInputName"></span><br/><small>This name must be unique across the whole of Wikipedia, so please make it informative and easy to recognize.<br/>It's no problem to use a fairly long name. It may also include spaces, commas and most other punctuation marks.<br/>Please also note that file names are case sensitive (with the exception of the first letter).<br/>'''Good:''' "City of London, skyline from London City Hall, Oct 2008.jpg". '''Bad''': "Skyline.jpg", "DSC0001234.jpg".</small></td> |- |} <div id="warningIllegalChars" class="uploadWarning" style="display:none;"> Sorry, a few special characters and character combinations cannot be used in the filename for technical reasons. This goes especially for '''#&nbsp;<&nbsp;>&nbsp;[&nbsp;]&nbsp;|&nbsp;:&nbsp;{&nbsp;}&nbsp;/&nbsp;''' and '''<nowiki>~~~</nowiki>'''. Your filename has been modified to avoid these. Please check if it is okay now. </div> <div id="warningBadFilename" class="uploadWarning" style="display:none;"> The filename you chose seems to be very short, or overly generic. Please don't use: *Titles that consist only of very generic descriptive words (e.g. "Sunset.jpg", "Townhall.jpg") *Titles that consist only of a person's first or last name, when that name is likely to be shared by many others (e.g. "John.jpg", "Miller.jpg") *Titles that consist of mere numbers, of the kind often produced by digital cameras ("DSC_001234", "IMGP0345"), or random strings like those sometimes found on the web ("30996951316264l.jpg") </div> <div id="warningImageOnCommons" class="uploadWarning" style="display:none;"> <div id="warningImageThumb" float="right"> <span class="fuwOutLink">[[File:Example.jpg|thumb|right|[[:File:Example.jpg|Existing file]].<br/><small>Last uploaded by <span id="existingImageUploader">Example user</span>.</small>]]</span> </div> '''A file of this name already exists on Commons!''' If you upload your file with this name, you will be masking the existing file and make it inaccessible. Your new file will be displayed everywhere the existing file was previously used. This should not be done, except in very rare exceptional cases. Please don't upload your file under this name, unless you seriously know what you are doing. Choose a different name for your new file instead. If you want to replace the existing file with an uncontroversial, improved version of the same work, please go to Commons and upload it there, not here on the Tulu Wikipedia's local wiki.</p> </div> <div id="warningImageExists" class="uploadWarning" style="display:none;"> '''A file of this name already exists.''' If you upload your file with this name, you will be overwriting the existing file. Your new file will be displayed everywhere the existing file was previously used. Please don't do this, unless you have a good reason to: {| |- |style=""|<span id="placeholderNoOverwrite"></span> |'''No''', I don't want to overwrite the existing file. I will choose a different name for my new file instead. |- |style=""|<span id="placeholderOverwriteSame"></span> |'''Yes''', I want to overwrite the existing file. My file is merely a new, improved and uncontentious version of the same work. The old description page, including the source and copyright information, will still be correct for the new version and can remain the same. |- |style=""|<span id="placeholderOverwriteDifferent"></span> |'''Yes''', I want to overwrite the existing file, and I will use this wizard to add a new description and new source information for it. The previous version was my own, or else I have made sure the previous uploader(s) don't object to this replacement. |- |} </div> <div id="UploadScriptStep2"> {| |- |colspan="2"|Please provide a brief description of the contents of this file.<br/><small>This will be stored and displayed as part of the file description page. It is important that other editors are able to understand what this file is about.</small> |- |class="uwLegend"|<span class="uwObligatory">&nbsp;</span></td> |style=""|<span id="placeholderInputDesc"></span><br/><small>What does this file show? What is it a photo/diagram/recording of?<br/>It will be helpful if you also add a <span class="fuwOutLink">[[Wikipedia:Cheatsheet#Internal link|wikilink]]</span> to the article where you want to use it.</small> |- |} </div> </div> <div id="UploadScriptStep3" class="uploadScriptSection"> ==ಸ್ಟೆಪ್ ೩: ಮೂಲೊ ಬುಕ್ಕೊ ಕೃತಿಸ್ವಾಮ್ಯದ ಮಾಹಿತಿನ್ ಕೊರ್ಲೆ== <p id="stepC_Start">It is very important that you read through the following options and questions, and provide all required information truthfully and carefully.</p> {| |- |style=""|<span id="placeholderOptionFree"></span> |'''This is a free work.''' <br/>I can demonstrate that it is legally okay for anybody to use, in Wikipedia and elsewhere, for any purpose. <div class="optionGroup" style="display:none;" id="detailsFreeStatus"> <div class="uploadWarning" style="display:none;" id="warningWhyNotCommons"> '''Thank you for offering to upload a free work.''' Wikipedia loves free files. However, we would love it even more if you uploaded them on our sister project, <span class="fuwOutLink">[[:commons:|Wikimedia Commons]]</span>. Files uploaded on Commons can be used immediately here on Wikipedia as well as on all its sister projects. Uploading files on Commons works just the same as here. Your Wikipedia account will automatically work on Commons too. [[File:Gtk-dialog-info.svg|30px|link=]] <big>'''Please consider <span class="fuwOutLink">[[:commons:Special:UploadWizard|uploading your file on Commons]]</span>.'''</big> However, if you prefer to do it here instead, you may go ahead with this form. You can also first use this form to collect the information about your file and then send it to Commons from here. </div> {| |- |colspan="2"|<span class="uwObligatory">Copyright status:</span> |- |style=""|<span id="placeholderOptionOwnWork"></span> |This file is '''entirely my own work.'''<br/><span id="smallNoteOwnWork">I am the copyright holder. I made this myself, from scratch, without copying or incorporating anybody else's creative work, and I am willing to release it under a free license.</span> <div class="uploadDetails" style="display:none;" id="detailsOwnWork"> <div class="uploadWarning" style="display:none;" id="warningOwnWork"> Please note that by "entirely self-made" we really mean just that. '''Do not''' use this section for any of the following: * a scan or photograph you made of a painting, drawing, printed page or other item originally created by somebody else. The copyright belongs to the original creator, not to you. * a screenshot or other kind of capture of a video, computer screen, TV programme or other kind of visual media. * a picture you created by modifying or copying some other picture or by combining several preexisting pictures made by somebody else. * a picture given to you by somebody else. * a picture you found somewhere on the Internet. Editors who falsely declare such items as their "own work" '''will be blocked from editing'''. </div> {| |- |colspan="2"|Please describe how and when you created this item. |- |class="uwLegend"|How? |style=""|<span id="placeholderOwnWorkCreation"></span> |- |&nbsp; |<small>(e.g.: Where and on what kind of occasion did you take this photo? How did you make this diagram? etc.)</small> |- |style=""|<span class="uwObligatory">Date</span> |style=""|<span id="placeholderDate"></span> |- |&nbsp; |<small>(please use YYYY-MM-DD format if possible).</small> |- |Publication: |style=""|<span id="placeholderOwnWorkPublication"></span><br/><small>Please indicate here if you have previously published this item elsewhere, e.g. on your own website, your Flickr or Facebook account, etc., providing a link.</small> |- |colspan="2"|It is important that you place this work under a free license, which will allow everybody else to use it for any purpose, including both commercial and non-commercial purposes, and to modify it. This license will be irrevocable. |- |colspan="2"|<span class="uwObligatory" id="placeholderOwnWorkLicense"></span> |- |}</div> |- |style=""|<span id="placeholderOptionThirdParty"></span></td> |This file was '''given to me by its owner.'''<br/>The copyright owner of this file has given it to me for uploading on Wikipedia. I can provide evidence that they have agreed to release it under a free license, for free use by anybody and for any purpose. <div class="uploadDetails" style="display:none;" id="detailsThirdParty"> {| |- |colspan="2"|Please describe who owns this work and how you got it from them. |- |class="uwLegend"|<span class="uwObligatory">Owner/author:</span> |style=""|<span id="placeholderAuthor"></span> |- |class="uwLegend"|Date of<br/>creation: |style=""|<span id="placeholderThirdPartyDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderSource"></span><br/><small>Where did you get the file from? (e.g. available online; was sent to me personally …)</small> |- |style=""|<span class="uwObligatory">Permission:</span> |style=""|<span id="placeholderPermission"></span><br/><small>How did you receive the permission? (e.g.: by e-mail, personally, I work for the owner …)</small> |- |colspan="2"|The copyright owner has chosen the following license: |- |style=""|<span class="uwObligatory">License:</span> |style=""|<span id="placeholderThirdPartyLicense"></span><br/>Other: <span id="placeholderThirdPartyOtherLicense"></span> |- |style=""|<span class="uwObligatory">Evidence:</span> | {| |- |style=""|<span id="placeholderThirdPartyEvidenceOptionLink"></span> |The license statement can be found online at:<br/><span id="placeholderThirdPartyEvidenceLink"></span> |- |style=""|<span id="placeholderThirdPartyEvidenceOptionOTRS"></span> |The license agreement has been forwarded to Wikimedia's volunteer response team at "permissions-en@wikimedia.org".<br/>OTRS ticket received: <span id="placeholderThirdPartyOTRSTicket"></span> |- |style=""|<span id="placeholderThirdPartyEvidenceOptionOTRSForthcoming"></span> |The license hasn't yet been forwarded, but I will do so shortly or ask the owner to send it. |- |style=""|<span id="placeholderThirdPartyEvidenceOptionNone"></span> |I haven't got the evidence right now, but I will provide some if requested to do so.<br /><small>Note: files without verifiable permissions may be deleted. You may be better off obtaining proof of permission first.</small> |- |} |- |}</div> |- |style=""|<span id="placeholderOptionFreeWebsite"></span></td> |This file is '''from a free published source.'''<br/>I took it from a website or other published source, where its author has explicitly placed it under a free license, allowing free re-use by anybody. <div class="uploadDetails" style="display:none;" id="detailsFreeWebsite"> <div class="uploadWarning" style="display:none;" id="warningFreeWebsite"> Use this '''only''' if there is an '''explicit licensing statement''' in the source. The website must explicitly say that the image is released under a license that allows free re-use for any purpose, e.g. the Creative Commons Attribution license. You must be able to point exactly to where it says this. If the source website doesn't say so explicitly, please '''do not upload the file'''. </div> {| |- |class="uwLegend"|<span class="uwObligatory">Author/owner:</span> |style=""|<span id="placeholderFreeWebsiteAuthor"></span> |- |class="uwLegend"|Date of<br/>creation: |style=""|<span id="placeholderFreeWebsiteDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderFreeWebsiteSource"></span><br/><small>For web sources: please provide a link to the html web page where the file can be found ("<nowiki>http://... .html</nowiki>"), not a direct link to the image file itself ("<nowiki>http://... .jpg</nowiki>").<br/>For print sources: provide full bibliographic information (author, title, publisher, year, page, etc.)</small> |- |colspan="2"|The copyright owner has chosen the following license for this file: |- |style=""|<span class="uwObligatory">License:</span> |style=""|<span id="placeholderFreeWebsiteLicense"></span><br/>Other: <span id="placeholderFreeWebsiteOtherLicense"></span> |- |style=""|<span class="uwObligatory">Evidence:</span> |style=""|<span id="placeholderFreeWebsitePermission"></span><br/>Provide a link to where the author '''explicitly says''' that the file is released under a free license.<br/><small>(if not visible on the source page itself).</small> |- |}</div> |- |style=""|<span id="placeholderOptionPDOld"></span> |This work is '''so old its copyright has expired.'''<br/>This is an old photograph, or a photographic reproduction of an old painting, drawing, etc. I can provide enough information about its author and provenance to prove that it is old enough for its copyright to have expired. It is now legally in the <span class="fuwOutLink">[[Public Domain]]</span>. <div class="uploadDetails" style="display:none;" id="detailsPDOld"> {| |- |class="uwLegend"|<span class="uwObligatory">Original<br/>author:</span> |style=""|<span id="placeholderPDOldAuthor"></span><br/><small>Please name the original author of this work.</small> |- |class="uwLegend"|<span class="uwObligatory">Lifetime:</span> |<span id="placeholderPDOldAuthorLifetime"></span><br/><small>Specify date of death, if applicable to public domain status.<br/>In many cases, we need to be certain the author died before a certain year, in many cases before {{Not-PD-US-expired-min-year}}.</small> |- |style=""|<span class="uwObligatory">Original<br/>publication:</span> |style=""|<span id="placeholderPublication"></span><br/><small>Provide as much information as possible about the original time and place of publication of this work. For print publications: provide full bibliographic information.</small> |- |style=""|<span class="uwObligatory">Date of<br/>publication:</span> |style=""|<span id="placeholderPDOldDate"></span><br/><small>Provide date of first publication, and date of creation if different.</small> |- |style=""|<span class="uwObligatory">Immediate<br/>source:</span> |style=""|<span id="placeholderPDOldSource"></span><br/><small>State exactly where you found this file. <br/>For web sources: please provide a link to the html web page where the file can be found ("<nowiki>http://... .html</nowiki>"), not a direct link to the image file itself ("<nowiki>http://... .jpg</nowiki>").<br/>For print sources: provide full bibliographic information (author, title, publisher, year, page, etc.)</small> |- |style=""|<span class="uwObligatory">Public Domain<br/>status:</span> |This work is free of all copyrights because: {| |- |style=""|<span id="placeholderPDUSExpired"></span> |It was created and '''first published before {{Not-PD-US-expired-min-year}}''' and is therefore in the Public Domain in the US. |- |style=""|<span id="placeholderPDURAA"></span> |It was '''first published outside the US''', and it was in the Public Domain in its country of origin by the "<span class="fuwOutLink">[[Uruguay Round Agreements Act|URAA date]]</span>".<br/><small>For most countries, this means the author died 70 years before 1 January 1996, i.e. before 1926. Please look up the copyright rules for the specific country at [http://copyright.cornell.edu/resources/publicdomain.cfm].</small> |- |style=""|<span id="placeholderPDFormality"></span> |It was '''first published in the US before 1989''', and its copyright expired because it was published without a copyright notice and/or without the necessary copyright registration.<br/><small>Please look up the exact rules at [http://copyright.cornell.edu/resources/publicdomain.cfm].</small> |- |style=""|<span id="placeholderPDOldOther"></span> |Its copyright expired for some other reason. [Please explain below]. |- |} |- |class="uwLegend"|Explanation: |style=""|<span id="placeholderPDOldPermission"></span><br/><small>Please provide any evidence necessary to verify the public domain status.</small> |- |}</div> |- |style=""|<span id="placeholderOptionPDOther"></span> |This file is '''in the Public Domain''' for some other reason.<br/>I can demonstrate that this work is legally in the Public Domain, i.e. nobody owns any copyrights on it. This may be for a variety of reasons, for instance because it was created by the US Federal Government, or because it is too simple to attract any copyright. <div class="uploadWarning" style="display:none;" id="warningPDOther"> '''Public Domain''' means that nobody owns any copyrights on this work. It does '''not''' mean simply that it is freely viewable somewhere on the web or that it has been widely used by others. This is '''not''' for images you simply found somewhere on the web. Most images on the web are under copyright and belong to somebody, even if you believe the owner won't care about that copyright. If it is in the public domain, you must be able to point to an actual law that makes it so. If you can't point to such a law but merely found this image somewhere, then '''please do not upload it.''' </div> <div class="uploadDetails" style="display:none;" id="detailsPDOther"> {| |- |class="uwLegend"|<span class="uwObligatory">Author:</span> |style=""|<span id="placeholderPDOtherAuthor"></span><br/><small>Please name the original author of this work.</small> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderPDOtherSource"></span><br/><small>State exactly where you found this file. <br/>For web sources: please provide a link to the html web page where the file can be found ("<nowiki>http://... .html</nowiki>"), not a direct link to the image file itself ("<nowiki>http://... .jpg</nowiki>").<br/>For print sources: provide full bibliographic information (author, title, publisher, year, page, etc.)</small> |- |class="uwLegend"|Date of<br/>creation: |style=""|<span id="placeholderPDOtherDate"></span> |- |style=""|<span class="uwObligatory">Public Domain<br/>status:</span> |This work is free of all copyrights because: {| |- |style=""|<span id="placeholderPDOtherUSGov"></span> |It was created by an agency of the US Federal Government.<br/><small>This does '''not''' apply to [[Copyright status of work by U.S. subnational governments|most US state and local agencies]], nor to governments of other countries!</small><br/><span id="placeholderUSGovLicense"></span> |- |style=""|<span id="placeholderPDOtherOfficial"></span> |It is an official governmental item, such as a flag, state emblem, banknote or postage stamp, from a country where such items are exempt from copyright according to local law.<br/><small>This does '''not''' apply to all countries, nor does it usually apply to '''all''' publications! (For instance, it usually doesn't apply to simple publicity photographs published on a governmental website.) Please look up the copyright rules for the specific country in question. If the country does not have an exemption rule that applies to this item, go on with the section for "[[#Non-free section|non-free copyrighted works]]" below.</small><br/><span class="uwObligatory">Explanation:</span> <span id="placeholderPDOfficialPermission"></span><br/><small>Add any explanation or evidence necessary to substantiate your statement above. Cite and provide a link to the relevant law if possible.</small> |- |style=""|<span id="placeholderPDOtherSimple"></span> |It is too simple to be eligible for copyright.<br/><small>This typically applies only to graphics that consist solely of simple geometric shapes and/or a few letters or words, or to items such as mathematical or chemical formulae. It may apply to some very simple logos that do not contain complex pictorial elements. It '''never''' applies to photographs!</small><br/><span class="uwObligatory" id="placeholderIneligibleLicense"></span> |- |style=""|<span id="placeholderPDOtherOther"></span> |It is in the Public Domain for some other reason.<br/><span class="uwObligatory">Explanation:</span> <span id="placeholderPDOtherPermission"></span> |- |} |- |}</div> |- |}</div> |- |style=""|<span id="placeholderOptionNonFree"></span> |<span id="Non-free section">'''This is a copyrighted, non-free work, but I believe it is Fair Use.'''</span><br/>I have read the Wikipedia rules on '''<span class="fuwOutLink">[[WP:NFC|Non-Free Content]]</span>''', and I am prepared to explain how the use of this file will meet the criteria set out there. It is '''not''' a photo from a press agency or photo agency (e.g., [[Associated Press|AP]] or [[Getty Images]]). <div class="uploadWarning" style="display:none;" id="warningNF"> [[File:Gtk-dialog-info.svg|15px|link=]] Please remember that you will need to demonstrate that: *The file will serve an important function in a particular article; <small class="fuwOutLink">([[WP:NFCC#8|NFCC8]])</small> *It cannot be replaced by any other, free illustration that might yet be created; <small class="fuwOutLink">([[WP:NFCC#1|NFCC1]])</small> *Its use does not negatively affect the commercial interests of its owner <small class="fuwOutLink">([[WP:NFCC#2|NFCC2]])</small> *There will not be more non-free material used than necessary. <small class="fuwOutLink">([[WP:NFCC#3|NFCC3]])</small> </div> <div id="detailsNFArticle" class="optionGroup" style="display:none;"> This file will be used in the following article: <span class="uwObligatory" id="placeholderNFArticle"></span><br/><small>Enter the name of exactly one Wikipedia article, without the <nowiki>[[...]]</nowiki> brackets and without the "<nowiki>http://en.wikipedia.org/...</nowiki>" URL code.<br/> It has to be an actual article, not a talkpage, template, user page, etc. <br/>If you plan to use the file in more than one article, please name only one of them here. Then, after uploading, open the image description page for editing and add your separate explanations for each additional article manually.</small> <div id="NFArticleOK" style="display:none;"> [[File:Gtk-ok.svg|15px|link=]] '''<span class="fuwOutLink">[[Example]]</span>''' – article okay. </div> <div id="warningNFArticleNotFound" class="uploadWarning" style="display:none;"> [[File:Gtk-dialog-warning.svg|20px|link=]] '''This article doesn't exist!''' The article <span class="fuwOutLink">[[Example]]</span> could not be found. Please check the spelling, and make sure you enter the name of an existing article in which you will include this file. If this is an article you are only planning to write, please write it first and upload the file afterwards. </div> <div id="warningNFArticleNotMainspace" class="uploadWarning" style="display:none;" > [[File:Gtk-dialog-warning.svg|20px|link=]] '''This is not an actual encyclopedia article!''' The page <span class="fuwOutLink">[[Example]]</span> is not in the main article namespace. Non-free files can only be used in mainspace article pages, not on a user page, talk page, template, etc. Please upload this file only if it is going to be used in an actual article. <div id="warningUserspaceDraft"> If this page is an article draft in your user space, we're sorry, but we must ask you to wait until the page is ready and has been moved into mainspace, and only upload the file after that. </div> </div> <div id="warningNFArticleDab" class="uploadWarning" style="display:none;"> [[File:Gtk-dialog-warning.svg|20px|link=]] '''This is a disambiguation page!''' The page <span class="fuwOutLink">[[Example]]</span> is not a real article, but a disambiguation page pointing to a number of other pages. Please check and enter the exact title of the actual target article you meant. </div> </div> <div id="detailsNFWorkType" class="optionGroup" style="display:none;"> {| |- |colspan="2"|<span class="uwObligatory">Non-free use rationale</span> |- |style=""|<span id="placeholderOptionNFSubject"></span> |This image '''is the object of discussion in an article.'''<br/>This is a copyrighted artwork or photograph, and the image itself is the topic of discussion in the article. The discussion is about the photograph or painting as such, as a creative work, '''not just about the thing or person it shows.''' <div class="uploadDetails" style="display:none;" id="detailsNFSubject"> {| |- |colspan="2"|Which of these options describes this item best? |- |colspan="2"|<span class="uwObligatory" id="placeholderNFSubjectLicense"></span> |- |colspan="2"|Who created this work? |- |class="uwLegend"|<span class="uwObligatory">Author/owner:</span> |style=""|<span id="placeholderNFSubjectAuthor"></span> |- |Date: |style=""|<span id="placeholderNFSubjectDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNFSubjectSource"></span><br/><small>State exactly where you found this file. <br/>For web sources: please provide a link to the html web page where the file can be found ("<nowiki>http://... .html</nowiki>"), not a direct link to the image file itself ("<nowiki>http://... .jpg</nowiki>").<br/>For print sources: provide full bibliographic information (author, title, publisher, year, page, etc.)</small> |- |} {| |- |colspan="2"|<span class="uwObligatory">Usage:</span> |- |style=""|<span id="placeholderNFSubjectCheckDedicated"></span> |The article as a whole is dedicated specifically to a discussion of this particular photograph/painting. (It is '''not''' just about the person or thing shown in the picture.) |- |style=""|<span id="placeholderNFSubjectCheckDiscussed"></span> |There is a substantial amount of encyclopedic discussion of this particular photograph/painting ('''not''' just about the person or thing shown in it) in this article. The illustration is specifically needed to support the following point:<br/><span id="placeholderNFSubjectPurpose"></span> <div id="warningNFSubject" class="uploadWarning" style="display:none;"> If neither of these two statements applies, then please '''do not upload this image.''' This section is '''not''' for images used merely to illustrate an article about a person or thing, showing what that person or thing look like. </div> |- |}</div> |- |style=""|<span id="placeholderOptionNF3D"></span> |This is a '''depiction of a copyrighted three-dimensional work or building''', which is the object of discussion in an article.<br/>This is a photograph or other kind of depiction of a copyrighted, three-dimensional creative work, such as a statue or work of architecture. The article contains a discussion of that work which requires illustration. The photograph as such is free, or was provided by the creator of the sculpture. <div class="uploadDetails" style="display:none;" id="detailsNF3D"> {| |- |colspan="2"|Which of these options describes this item best? |- |colspan="2"|<span class="uwObligatory" id="placeholderNF3DLicense"></span> |- |colspan="2"|First describe who created the '''original work''' depicted: |- |class="uwLegend"|<span class="uwObligatory">Creator:</span> |style=""|<span id="placeholderNF3DCreator"></span> |- |Date: |style=""|<span id="placeholderNF3DOrigDate"></span> |- |} {| |- |colspan="2"|<span class="uwObligatory">Usage:</span> |- |style=""|<span id="placeholderNF3DCheckDedicated"></span> |The article as a whole is dedicated specifically to this work. |- |style=""|<span id="placeholderNF3DCheckDiscussed"></span> |There is a substantial amount of encyclopedic discussion of this work in this article. The illustration is specifically needed to support the following point:<br/><span class="uwObligatory"></span><span id="placeholderNF3DPurpose"></span> |} {| |- |colspan="2"|Now describe who created '''the image''': |- |class="uwLegend"|<span class="uwObligatory">Author:</span> |style=""|<span id="placeholderNF3DAuthor"></span> |- |Date: |style=""|<span id="placeholderNF3DDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNF3DSource"></span><br/><small>State exactly where you found this file.<br/>For web sources: please provide a link to the html web page where the file can be found ("<nowiki>http://... .html</nowiki>"), not a direct link to the image file itself ("<nowiki>http://... .jpg</nowiki>").<br/>For print sources: provide full bibliographic information (author, title, publisher, year, page, etc.)</small> |- |} {| |- |colspan="2"|<span class="uwObligatory">Image status</span> |- |style=""|<span id="placeholderNF3DOptionSame"></span> |The image was created and published by the same author who also holds the rights to the original object, and no alternative depiction could be suitably created. |- |style=""|<span id="placeholderNF3DOptionFree"></span> |The author of the image has released the photographic work under a free license, or it is in the public domain:<br/><span class="uwObligatory" id="placeholderNF3DPermission"></span><br/><small>Name the license or describe the public domain status, adding any necessary evidence to make the licensing status verifiable.</small> |- |}</div> |- |style=""|<span id="placeholderOptionNFExcerpt"></span> |This is an '''excerpt from a copyrighted work'''.<br/>This is an excerpt from a copyrighted work, e.g. a screenshot from a movie or TV programme, a panel from a comic, or a sound sample from a song. Its presence is needed to support a piece of explicit critical discussion in an article related to that work or its creator(s). <div class="uploadDetails" style="display:none;" id="detailsNFExcerpt"> {| |- |colspan="2"|Which of these options describes this item best? |- |colspan="2"|<span class="uwObligatory" id="placeholderNFExcerptLicense"></span> |- |style=""|<span class="uwObligatory">Author:</span> |style=""|<span id="placeholderNFExcerptAuthor"></span><br/><small>(author / copyright owner of the original work)</small> |- |Date of<br/>creation: |style=""|<span id="placeholderNFExcerptDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNFExcerptSource"></span><br/><small>(where exactly did you get this file from?)</small> |- |colspan="2"|Please explain what exactly in the article it is that you want to illustrate with this. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFExcerptPurpose"></span><br/><small>Typically, the illustration must be used to support some specific issue of discussion in the article.<br/> Please be concrete and specific. Don't just copy boilerplate statements from elsewhere. State clearly, in your own words, what this particular file will be doing in this particular article.</small> |- |colspan="2"|If necessary, please explain why this purpose cannot be achieved through text alone. |- |&nbsp; |style=""|<span id="placeholderNFExcerptReplaceable"></span> |- |}</div> |- |style=""|<span id="placeholderOptionNFCover"></span> |This is the '''official cover art''' of a work.<br/>This is the cover or dustjacket of a book, the cover of a CD or video, the official release poster of a movie, or a comparable item. It will be included as that work's primary means of visual identification, at the top of the article about the book, movie, etc. in question. <br/><small>Note: If you plan to use it for any other purpose than this, please tick the box for "other non-free work" below.</small> <div class="uploadDetails" style="display:none;" id="detailsNFCover"> {| |- |colspan="2"|Which of these options describes this item best? |- |colspan="2"|<span class="uwObligatory" id="placeholderNFCoverLicense"></span> |- |style=""|<span class="uwObligatory">Author:</span> |style=""|<span id="placeholderNFCoverAuthor"></span><br/><small>(author / copyright owner of the original work)</small> |- |Date of<br/>publication: |style=""|<span id="placeholderNFCoverDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNFCoverSource"></span><br/><small>(where exactly did you get this file from?)</small> |- |colspan="2"|<span class="uwObligatory" id="placeholderNFCoverCheckDedicated"></span>This image will be shown as a primary means of visual identification at the top of the article dedicated to the work in question.<br/><small>A standard fair use rationale will be added that matches this type of use. If you plan to use the file for any purpose other than this, please do '''not''' use this section, but the one labelled "other type of non-free work" below.</small> |- |}</div> |- |style=""|<span id="placeholderOptionNFLogo"></span> |This is a '''logo of an organization''', company, brand, etc.<br/>This is an official logo of an entity that is the subject of a Wikipedia article. It will be included as that entity's primary means of visual identification, at the top of the article in question. <br/><small>Note: If you plan to use it for any other purpose than this, please tick the box for "other non-free work" below.</small> <div class="uploadDetails" style="display:none;" id="detailsNFLogo"> {| |- |colspan="2"|Which of these options describes this item best? |- |colspan="2"|<span class="uwObligatory" id="placeholderNFLogoLicense"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNFLogoSource"></span><br/><small>(where exactly did you get this file from?)</small> |- |td colspan="2"|<span class="uwObligatory" id="placeholderNFLogoCheckDedicated"></span>This image will be shown as a primary means of visual identification at the top of the article dedicated to the entity in question.<br/><small>A standard fair use rationale will be added that matches this type of use. If you plan to use the file for any purpose other than this, please do '''not''' use this section, but the one labelled "other type of non-free work" below.</small> |- |}</div> |- |style=""|<span id="placeholderOptionNFPortrait"></span> |This is a '''historical portrait''' of a person no longer alive.<br/>This is a historical photograph or other depiction of a person who is no longer alive. It will be used as the primary means of visual identification of that person in the article about them. <div class="uploadDetails" style="display:none;" id="detailsNFPortrait"> {| |- |style=""|<span class="uwObligatory">Deceased since:</span> |style=""|<span id="placeholderNFPortraitDeceased"></span><br/><small>(This type of file can typically only be used with people who are no longer alive.)</small> |- |style=""|<span class="uwObligatory">Author:</span> |style=""|<span id="placeholderNFPortraitAuthor"></span><br/><small>(Who made this image?)</small> |- |style=""|<span class="uwObligatory">Original<br/>publication:</span> |style=""|<span id="placeholderNFPortraitPublication"></span><br/><small>(Where, when and how was this image first published?)</small> |- |Date of<br/>publication: |style=""|<span id="placeholderNFPortraitDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNFPortraitSource"></span><br/><small>(Where exactly did you get this file from?)</small> |- |colspan="2"|<span class="uwObligatory" id="placeholderNFPortraitCheckDedicated"></span>This image will be shown as a primary means of visual identification at the top of the article dedicated to the person in question.<br/><small>A standard fair use rationale will be added that matches this type of use. If you plan to use the file for any purpose other than this, please do '''not''' use this section, but the one labelled "other type of non-free work" below.</small> |- |colspan="2"|Please explain why a free alternative to this image cannot be found. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFPortraitReplaceable"></span><br/><small>For subjects who died recently: have you made a reasonable effort to find people who might possess photographs of this person and might be willing to release one?<br/>For subjects who lived in the early-to-mid 20th century: have you considered if there might be an older photograph that has fallen in the public domain?</small> |- |colspan="2"|Please explain why you are confident that our use of the file will not harm any commercial opportunities of its owner. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFPortraitCommercial"></span><br/><small>We will typically not use a file if its owner has a potential commercial interest in its use, and if our use of it would compete with its original market role.</small> |- |}</div> |- |style=""|<span id="placeholderOptionNFMisc"></span> |This is '''some other kind of non-free work''' that I believe is legitimate Fair Use.<br/>This is a copyrighted work whose use does not fall into any of the classes above. I have read the Wikipedia rules on <span class="fuwOutLink">[[Wikipedia:Non-free content|Non-free content]]</span>, and I will explain how this file meets all of the criteria set out there. <div class="uploadDetails" style="display:none;" id="detailsNFMisc"> {| |- |colspan="2"|Which of these options describes this item best? |- |colspan="2"|<span class="uwObligatory" id="placeholderNFMiscLicense"></span> |- |class="uwLegend"|<span class="uwObligatory">Author:</span> |style=""|<span id="placeholderNFMiscAuthor"></span><br/><small>(Who made this image?)</small> |- |style=""|<span class="uwObligatory">Original<br/>publication:</span> |style=""|<span id="placeholderNFMiscPublication"></span><br/><small>(Where, when and how was this image first published?)</small> |- |Date of<br/>publication: |style=""|<span id="placeholderNFMiscDate"></span> |- |style=""|<span class="uwObligatory">Source:</span> |style=""|<span id="placeholderNFMiscSource"></span><br/><small>(Where exactly did you get this file from?)</small> |- |colspan="2"|Please explain what exact purpose this file will serve in the article. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFPurpose"></span><br/><small>Please be concrete and specific. Don't just copy boilerplate statements from elsewhere. State clearly, in your own words, what this particular file will be doing in this particular article. Your explanation must make it clear why the article would be significantly worse off without this file.</small> |- |colspan="2"|Please explain why this purpose could not be served by text alone. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFReplaceableText"></span> |- |colspan="2"|Please explain why this purpose could not be served with an alternative, free illustration that could yet be found or created. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFReplaceable"></span><br/><small>For a file to be deemed replaceable, it is not necessary that a suitable replacement already exists. Even if it is merely possible that a replacement could be created, we will not use the non-free file.</small> |- |colspan="2"|Please explain why you are confident that our use of the file will not harm any commercial opportunities of its owner. |- |style=""|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFCommercial"></span><br/><small>We will typically not use a file if its owner has a potential commercial interest in its use, and if our use of it would compete with its original market role.</small> |- |} {|style="width:100%" id="NFMinimalitySection" |- |colspan="2"|Remember that the use of non-free files must be '''minimal.''' This can mean several things: {{smalldiv| *Don't use more files per article/topic than necessary *Don't use the same file in more articles than necessary *Don't use larger excerpts of a single work than necessary *Don't use images of higher resolution than necessary}} In view of this, please explain how the use of this file will be minimal. |- |class="uwLegend"|<span class="uwObligatory">&nbsp;</span> |style=""|<span id="placeholderNFMinimality"></span> |- |colspan="2"|Special source and license conditions (optional) |- |class="uwLegend"|&nbsp; |style=""|<span id="placeholderNFExtraLicense"></span> |- |} {|style="width:100%" id="AnyOtherInfo" |- |colspan="2"|Any further relevant information about this file? |- |class="uwLegend"|&nbsp; |style=""|<span id="placeholderAnyOther"></span> |- |colspan="2"|<div id="fuwSubmitHost"><div id="fuwSubmit" style="border:1px solid var(--border-color-success,#099979);color:inherit;background:var(--background-color-success-subtle,#dff2eb);margin:0.5em;padding:0.5em;"> <div id="EditSummaryDiv" style="display:none;"> {| |class="uwLegend"|Edit summary: |<span id="placeholderEditSummary"></span><br/><small>A brief description of why you are overwriting this file. This will not be saved on the description page, but will be shown in its edit history.</small> |} </div> <div id="sendToCommons"> {| |style="width:12em;"|<span id="placeholderCommonsButton"></span> |'''Yes''', I want this file to be immediately available in all Wikimedia projects, in all languages. I will upload it on the '''Wikimedia Commons'''. <br/><small>Clicking this button will redirect you to a page on Commons. This will only work if you are already logged in there, which is likely the case. Check <span class="fuwOutLink" id="commonsLoginLink">[[:commons:Special:UserLogin|here]]</span> to see if you are logged in.</small> |} </div> {| |style="width:12em;"|<span id="placeholderSubmitButton"></span> |<span id="fuwSubmitText">'''No''', I want to upload this file locally.<br/><small>This way it can be used only on the Tulu Wikipedia. We urge you to upload it to the Commons unless there is a very good reason for it to stay local. Often such local files are copied to the Commons for use elsewhere and deleted locally, requiring extra work for other volunteers. If you do ''not'' want your file to be copied to Commons and deleted locally, consider adding the &#123;&#123;Keep local&#125;&#125; tag.</small></span> |- |<span id="placeholderResetButton1"></span> |Reset this form and start over. |} </div></div> |- |}</div> |- |}</div> |- |style=""|<span id="placeholderOptionNoGood"></span> |'''This file doesn't fit either of the categories above.''' <br/>This file doesn't seem to fall into either of the classes above, or I am not certain what its status is. I found this file somewhere, but I don't really know who made it or who owns it. <div class="uploadWarning" style="display:none;" id="warningNoGood"> Well, we're very sorry, but if you're not sure about this file's copyright status, or if it doesn't fit into any of the groups above, then: <big>'''Please don't upload it.'''</big> Really, please don't. Even if you think it would make for a great addition to an article. We really take these copyright rules very seriously on Wikipedia. Note that media is ''assumed'' to be fully-copyrighted unless shown otherwise; the burden is on the uploader. In particular, please don't upload: *any file you simply found on some website, without knowing who its author or copyright owner is. *any file you found somewhere, even if you have good reason to believe it has a copyright owner who would not mind us using it, but you don't have an explicit licensing statement from them. *any file that was released for publicity purposes by its owners but doesn't have a fully-free license for free re-use for all purposes. *any file credited to a commercial image agency, such as Reuters, AP or Getty Images. Such files normally cannot be used even under the "Fair Use" rules, except in rare cases. *any file that is licensed for use exclusively on Wikipedia, or is free except that the free license excludes commercial use. If you are in any doubt, please ask some experienced editors for advice before uploading. People will be happy to assist you at <span class="fuwOutLink">[[Wikipedia:Media copyright questions]]</span>. Thank you. </div> |- |}</div></div></div> <div id="placeholderTestForm" style="border:2px solid green;padding:0.5em;margin:0.5em;background:#D0D0D0;display:none;"> ==Preview (test)== This is the data that will be submitted to upload: {| |- |Filename:||<span id="placeholderSandboxFilename"></span> |- |Edit summary:||<span id="placeholderSandboxSummary"></span> |- |Text:||<span id="placeholderSandboxText"></span> |- |} <!-- Hidden fields for edit-in-sandbox form --> <span id="placeholderSandboxToken"></span> <span id="placeholderSandboxTitle"></span> <span id="placeholderSandboxRecreate"></span> <!-- end of hidden fields --> </div> <div id="fuwWaiting" style="display:none;"> ==Upload in process== Your file is being uploaded. This might take a minute or two, depending on the size of the file and the speed of your internet connection. Once uploading is completed, you will find your new file at this link: <span id="fuwSuccessLink">'''[[:File:Example.jpg]]'''</span> </div> <div id="fuwSuccess" style="display:none;"> ==File successfully uploaded== <div id="successThumb" style="float:right;display:none;">[[File:Example.jpg]]</div> Your file has been uploaded successfully and can now be found here: <span id="fuwSuccessLink2">'''[[:File:Example.jpg]]'''</span> Please follow the link and check that the image description page has all the information you meant to include. If you want to change the description, just go to the image page, click the "edit" tab at the top of the page and edit just as you would edit any other page. Do not go through this upload form again, unless you want to replace the actual file with a new version. To insert this file into an article, you may want to use code similar to the following: <nowiki>[[</nowiki>File:<span id="placeholderExFilename1">Example.jpg</span>|thumb|right|insert a caption here<nowiki>]]</nowiki> If you wish to make a link to the file in text, without actually showing the image, for instance when discussing the image on a talk page, you can use the following (mark the ":" after the initial brackets!): <nowiki>[[</nowiki>:File:<span id="placeholderExFilename2">Example.jpg</span><nowiki>]]</nowiki> See [[Wikipedia:Picture tutorial]] for more detailed help on how to insert and position images in pages. '''Thank you for using the File Upload Wizard.'''<br/>Please leave your feedback, comments, bug reports or suggestions on the [[{{TALKPAGENAME}}|talk page]]. <span id="placeholderResetButton2"></span> </div> <div id="fuwFooter" style="padding-bottom:1.5em;"> {{Navbox | name = ಮಾಧ್ಯಮ ಫೈಲ್‌ಲೆನ್ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುನಗ | state = plain | bodyclass = plainlist | style = width:auto; | navbar = plain | title = ಮಾಧ್ಯಮ ಫೈಲ್‌ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪರ | list1 = {{Navbox with columns |child | state = plain | style = padding-bottom:0.6em; | colstyle = font-size:110%;text-align:center;white-space:nowrap; | col1header = [[ವಿಕಿಮೀಡಿಯಾ ಕಾಮನ್ಸ್|ಕಾಮನ್ಸ್]] | col1 = <div style="width:14.0em;margin:0 auto;"> * {{longitem|style=line-height:1.1em;padding:0.5em 0|[[:Commons:Special:UploadWizard|ಕಾಮನ್ಸ್ ವಿಜಾರ್ಡ್]]<br/>{{smaller|(ದರ್ಮೊದ ಫೈಲ್‌ಲೆಗ್ ಶಿಫಾರಸ್ ಮಲ್ಪುನವು)}}}} * {{longitem|style=line-height:1.1em;padding-bottom:0.5em|[[:Commons:Special:Upload|ಕಾಮನ್ಸ್‌ಗ್ ಸರಳ ರೂಪ]]<br/>{{smaller|(ಮಸ್ತ್ ತೆರಿನ ಬಳಕೆದಾರೆರ್)}}}} * [[:Commons:Commons:Upload|ಪರತ್ ರೂಪ]] </div> | col2header = ವಿಕಿಪೀಡಿಯ | col2 = <div style="width:14.0em;margin:0 auto;"> * {{longitem|style=line-height:1.1em;padding:0.5em 0|[[ವಿಕಿಪೀಡಿಯ:ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುನ ಫೈಲ್‌ಲು|''ಫೈಲ್ ಅಪ್‌ಲೋಡ್ ಮಲ್ಪುನ'' ಪ್ರಕ್ರಿಯೆ]]<br/>{{smaller|(ಪೊಸ ಬಳಕೆದಾರೆರೆಗಾದ್)}}}} * {{longitem|style=line-height:1.1em;padding-bottom:0.5em|[[Special:Upload|ಸ್ಥಳೀಯ ಅಪ್‌ಲೋಡ್‌ಲೆಗ್ ಸುಲಬೊ ರೂಪೊ]]<br/>{{smaller|(ಮಸ್ತ್ ತೆರಿನ ಬಳಕೆದಾರೆರ್)}}}} * [[ವಿಕಿಪೀಡಿಯ:ಅಪ್‌ಲೋಡ್/ಪರತ್|ಪಿರಾಕ್‌ದ ಮಾರ್ಗದರ್ಶಿ ರೂಪ]] </div> }} | group2 = ಸಕಾಯೊ ಬುಕ್ಕೊ ಮಾರ್ಗದರ್ಶನೊಲು | list2style = padding-right:1.25em; | list2 = {{startflatlist}} * <span class="fuwOutLink">[[Wikipedia:Media copyright questions|Ask copyright questions]]</span> * <span class="fuwOutLink">[[Wikipedia:Image use policy|Image use policy]]</span> * <span class="fuwOutLink">[[WP:NFC|Non-free content]]</span> {{endflatlist}} | group3 = This wizard | list3 = {{startflatlist}} * <span class="fuwOutLink">[[:{{FULLPAGENAME}}/doc|Documentation]]</span> * <span class="fuwOutLink">[[:MediaWiki:FileUploadWizard.js|ಸ್ಕ್ರಿಪ್ಟ್]]</span> * <span class="fuwOutLink">[[{{TALKPAGENAME}}|ಚರ್ಚೆ]]</span> {{endflatlist}} }} </div> neuxdnizya6ak2a88hxbjx2ru2385th ಕೋಲಾಟ್ಟಂ 0 24726 360801 360554 2026-05-16T07:38:13Z ChiK 1136 null #proveit 360801 wikitext text/x-wiki ==ಕೋಲಾಟ್ಟಂ ಜಾನಪದ ನಲಿಕೆ== [[File:Procession at Bhadrachalam 12.jpg|thumb|ಕೋಲಾಟ್ಟಂ ಜಾನಪದ ನಲಿಕೆ]] ಕೋಲಾಟ್ಟಂ ಪಂಡ ಪ್ರಧಾನವಾದ್ [[ತಮಿಳುನಾಡು]] ಬೊಕ್ಕ [[ಕೇರಳ|ಕೇರಳಡ್]] ನಲಿಪುನ ಪಿರಾಕ್‌ದ ಜಾನಪದ ನಲಿಕೆ. ಉಂದು ಸಾಮಾನ್ಯವಾದ್ ಪೊಣ್ಣುಲು ರಡ್ಡ್ ಎಲ್ಯ ಮರತ ಕಡ್ಡಿಲೆನ್, ಒಂಜಿ ಕೈಟ್ ಒಂಜಿ ಕಡ್ಡಿನ್ ಬಳಸೊಂದು ಮಲ್ಪುವೆರ್. ನಲಿಕೆದಾರೆರ್ ಸಾಮಾನ್ಯವಾದ್ ಒಂಜಿ ವೃತ್ತಾಕಾರೊಡು ನಿಲೆ ಆದ್ ಜಾನಪದ ಗೀತೆಲೆನ್ ಪಾಡುನಗ ನಿರ್ದಿಷ್ಟ ಲಯೊಲೆನ್ ಮಲ್ಪೆರೆ ಕಡ್ಡಿಲೆನ್ ದಾಂಟುವೆರ್. ಈ ನಲಿಕೆನ್ ಸಾಮಾನ್ಯವಾದ್ ಹಿಂದೂ ದೇವೆರ್ ಅತ್ತ್ಂಡ ದೇವತೆಲೆಗ್ ಸಮರ್ಪಣೆ ಮಲ್ಪುವೆರ್ ಬೊಕ್ಕ ಸುಗ್ಗಿದ ಕಾಲೊಡು ಬೊಕ್ಕ ಗ್ರಾಮದ ಪರ್ಬೊಲೆಡ್ ಮಲ್ಪುವೆರ್. ಕೋಲಾಟ್ಟಂ ಪಂಡ ದಕ್ಷಿಣ ಭಾರತೊದ ಒಂಜಿ ಪ್ರಾಚೀನ ಜಾನಪದ ನಲಿಕೆ.ಸಾಮಾನ್ಯವಾದ್ ಮಾತಾ ಪ್ರಾಯೊದ ಪೊಣ್ಣುಲು ನಲಿಕೆ ಮಲ್ಪುವೆರ್. ಉಂದು ಒಂಜಿ ಸಮುದಾಯ ಅತ್ತಂಡ ಕೋರಸ್ ನಲಿಕೆ, ಉಂದೆನ್ ಗುಂಪುಗುಂಪು ಆದ್ ಮಲ್ಪುವೆರ್. "ಕೊಲಟ್ಟಂ" ಪನ್ಪಿನ ಪುದರ್ ತಮಿಳು ಭಾಷೆಡ್ ಕೋಲ್ ಪಂಡ "ಕಡ್ಡಿ" ಬೊಕ್ಕ ಅಟ್ಟಮ್ ಪಂಡ "ನಲಿಕೆ" ಪನ್ಪಿನ ಪುದರ್ ಡ್ದ್ ಬತ್ತ್ಂಡ್. ನಲಿಕೆದಕುಲು ರಡ್ಡ್ ಎಲ್ಯ ಕಡ್ಡಿಲೆನ್ ಬಳಸುವೆರ್. ಸಾಮಾನ್ಯವಾದ್ ಸುಮಾರ್ 14 ಮೀ. ಉದ್ದೊಡು, ಪ್ರತಿಯೊಂಜಿ ಕೈಟ್ ಒಂಜೊಂಜಿ ಕಡ್ಡಿ ಪತ್ತ್ದ್ ನಲಿಪುವೆರ್, ನರ್ತಕಿಲು ಸಾಮಾನ್ಯವಾದ್ ಒಂಜಿ ವೃತ್ತಾಕಾರೊಡು ನಿಲೆ ಆದ್ ಬೇತೆ ಬೇತೆ ಜಾನಪದ ಗೀತೆಲೆನ್ ಪಾಡುನಗ ನಿರ್ದಿಷ್ಟ ಲಯೊಗ್ ನಲಿಪುವೆರ್. ನರ್ತಕಿಲು ಅಕ್ಲೆನ ಕೈಟ್ ದೀತಿನ ಕಡ್ಡಿಲೆನ್ ಗುದ್ದುದು ಶಬ್ದೊಲೆನ್ ಮಲ್ಪೆರ್. ==ಆಚರಣೆ== ಈ ನಲಿಕೆನ್ ಸಾಮಾನ್ಯವಾದ್ ಹಿಂದೂ ದೇವೆರೆಗ್ ಅತ್ತ್ಂಡ ದೇವತೆಲೆಗ್ ಸಮರ್ಪಿಸವೆರ್. ಈ ನಲಿಕೆನ್ [[ಸುಗ್ಗಿದ ನಲಿಕೆ|ಸುಗ್ಗಿ]]ದ ಕಾಲೊಡು ಬೊಕ್ಕ ತಮಿಳು ಕ್ಯಾಲೆಂಡರ್ ದ ಕಾರ್ತಿಕ ಮಾಸೊಡು ಒಂಜಿ ಪಕ್ಷೊಗು ಮಲ್ಪುವೆರ್. ಈ ನಲಿಕೆನ್ ಗ್ರಾಮದ ಪರ್ಬೊಲೆಡ್ ಬೊಕ್ಕ ಜಾತ್ರೆಲೆಡ್ ಅಯಿತ ಭಾಗವಾದ್ ಮಲ್ಪುವೆರ್.<ref>{{Cite web |url=https://dallasnatyalaya.com/index.php/our-styles/ |title=OUR STYLES |accessdate=2026-05-16 |language=en-US}}https://dallasnatyalaya.com/index.php/our-styles/{{Dead link|date=May 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> ದಕ್ಷಿಣ ಭಾರತೊಡು ಮುಖ್ಯವಾದ್ ತಮಿಳುನಾಡು ಬೊಕ್ಕ ಕೇರಳೊಡು ಬೊಕ್ಕ ಶ್ರೀಲಂಕಾ ಬೊಕ್ಕ ಮಲೇಷ್ಯಾದಂಚಿನ ಮಹತ್ವದ ತಮಿಳು ವಲಸೆ ಉಪ್ಪುನ ಬೇತೆ ಪ್ರದೇಶೊಲೆಡ್ ಈ ನಲಿಕೆನ್ ಮಲ್ಪುವೆರ್. ಈ ನಲಿಕೆನ್ ಧಾರ್ಮಿಕ ಸಮಾರಂಭೊಲೆಡ್, ಸಮಾರಂಭೊಲೆಡ್ ಬೊಕ್ಕ ಪೊಂಗಲ್ ದಂಚಿನ ಪರ್ಬೊಲೆಡ್ ಮಲ್ಪುವೆರ್, ಸಾಮಾನ್ಯವಾದ್ ಪೊಣ್ಣುಲು. ಸರಿಯಾಯಿನ ನಲಿಕೆಗ್ ಜಟಿಲವಾದ್ ಚಲನೆಲೆನ್ ಮಲ್ಪುನ ತಂತ್ರ ಬೊಕ್ಕ ಕೌಶಲ್ಯ ಬೋಡಾಪುಂಡು, ಉಂದೆನ್ ಹವ್ಯಾಸಿ ನರ್ತಕಿಲುಲಾ ಅಭ್ಯಾಸ ಮಲ್ಪುವೆರ್.<ref>{{Cite web |url=https://www.urbanpro.com/choreography/folk-dance-kolattam |title=Folk Dance KOLATTAM - UrbanPro |accessdate=2026-05-16 |website=UrbanPro.com |language=en}}https://www.urbanpro.com/choreography/folk-dance-kolattam</ref> ==ನಲಿಕೆದ ಬೇತೆ ವಿಧೊಕ್ಲು,ಬದಲಾವಣೆಲು== [[File:Koltam jpg.jpg|thumb|ಕೋಲಾಟ್ಟಂ]] ಪಿನ್ನಾಲ್ ಕೋಲಾಟ್ಟಂ (ಕೋಲಟ್ಟಂ ದ ಒಂಜಿ ಜಟಿಲ ರೂಪ) ಬೊಕ್ಕ ಚಕ್ಕೆ ಕೋಲಾಟ್ಟಂ ಇಂಚಿನ ಬೇತೆ ಬೇತೆ ರೂಪೊಲು ಉಂಡು.ಪಿನ್ನಾಲ್ ಕೋಲಾಟ್ಟಂ ಕಡ್ಡಿಲೆನ ಬದಲ್ ಬಳ್ಳ್ ಬಳಸುವೆರ್. ಕುಮ್ಮಿಅಟ್ಟಂ ಪಂಡ ಕೊಲತ್ತಮ್ ಲೆಕ್ಕನೆ ಉಪ್ಪುನ ಒಂಜಿ ಜಾನಪದ ನಲಿಕೆ, ವ್ಯತ್ಯಾಸ ಪಂಡ ಕುಮ್ಮಿಅಟ್ಟಂ ಡ್ ನಲಿಪುನಗ ಕಡ್ಡಿಲೆನ ಬದಲ್ ಕೈನ್ ಶಬ್ದ ಮಲ್ಪೆರೆ ಬಳಸುವೆರ್. [[ಆಂಧ್ರ ಪ್ರದೇಶ|ಆಂಧ್ರಪ್ರದೇಶ]] ಬೊಕ್ಕ ತೆಲಂಗಾಣೊಡು ನಲಿಕೆ ಮಲ್ಪುನ ಒಂಜೇ ರೀತಿದ ನಲಿಕೆನ್ ಕೊಲನಾಲು ಪನ್ಪೆರ್. ಕರ್ನಾಟಕೊಡು ಉಂದೆನ್ ಕೋಲಾಟ ಪಂಡ್ದ್ ಲೆಪ್ಪುವೆರ್. [[ಗುಜರಾತ್]] ಬೊಕ್ಕ ಉತ್ತರ ಭಾರತದ ಕೆಲವು ಭಾಗೊಲೆಡ್ ಅಭ್ಯಾಸ ಮಲ್ಪುನ ದಂಡಿಯಾ ರಾಸ್ ಡ್ ಒಂಜೇ ರೀತಿದ ಕಡ್ಡಿಲೆನ್ ಬಳಕೆ ಮಲ್ಪುವೆರ್. ಬೊಕ್ಕ ಕೊಲತ್ತಮ್ ನೊಟ್ಟುಗು ಕೆಲವು ಸಾಮ್ಯತೆಲಾ ಉಂಡು. ಕೆಲವೊಂಜಿ ಸರ್ತಿ, ನಲಿಕೆಗ್ ಕಡ್ಡಿಲೆನ ಬದಲ್ ಉದ್ದದ ಬಣ್ಣದ ರಿಬ್ಬನ್ ಲೆನ್ ಬಳಕೆ ಮಲ್ಪುವೆರ್. ಇತ್ತೆದ ವರ್ಷೊಲೆಡ್, ಪುರುಷೆರ್ ಬೊಕ್ಕ ಜೋಕುಲು ಶಾಲೆದ ಉತ್ಸವೊಲೆಡ್ ನಲಿಪುವೆರ್.<ref>{{Cite web |url=https://prepp.in/news/e-492-kummi-indian-folk-dances-art-and-culture-notes |title=Indian Administrative Service - IAS Exam |accessdate=2026-05-16 |website=Prepp |language=en}}https://prepp.in/news/e-492-kummi-indian-folk-dances-art-and-culture-notes</ref> {{Reflist}} ವರ್ಗ:ಸ್ತ್ರೀವಾದೊ ಬುಕ್ಕೊ ಜಾನಪದೊ 2026 nq1ntlix0hq796tj0bnc4w9usz5hkmy ವರ್ಗೊ:ಪಗ್ಗು 14 26724 360724 358945 2026-05-16T07:21:20Z ChiK 1136 removed [[Category:ತುಳು ತಿಂಗೊಲು]] using [[Help:Gadget-HotCat|HotCat]] 360724 wikitext text/x-wiki ಉಂದು ತುಳುವೆರೆ ತಿಂಗೊಲ್ದ ಪುದಾರ್. ಈ ವರ್ಗೊಡು ಪಗ್ಗು ತಿಂಗೊಲುಡು ನಡಪುನ ಆಚರಣೆಲೆನ್ ಸೇರಾವೊಲಿ. 9d2ndw9x1oj7i6jyhx3fj1aipy82qwh