Index: trunk/extensions/TradeTrack/LICENSE |
— | — | @@ -0,0 +1,339 @@ |
| 2 | + GNU GENERAL PUBLIC LICENSE |
| 3 | + Version 2, June 1991 |
| 4 | + |
| 5 | + Copyright (C) 1989, 1991 Free Software Foundation, Inc., |
| 6 | + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 7 | + Everyone is permitted to copy and distribute verbatim copies |
| 8 | + of this license document, but changing it is not allowed. |
| 9 | + |
| 10 | + Preamble |
| 11 | + |
| 12 | + The licenses for most software are designed to take away your |
| 13 | +freedom to share and change it. By contrast, the GNU General Public |
| 14 | +License is intended to guarantee your freedom to share and change free |
| 15 | +software--to make sure the software is free for all its users. This |
| 16 | +General Public License applies to most of the Free Software |
| 17 | +Foundation's software and to any other program whose authors commit to |
| 18 | +using it. (Some other Free Software Foundation software is covered by |
| 19 | +the GNU Lesser General Public License instead.) You can apply it to |
| 20 | +your programs, too. |
| 21 | + |
| 22 | + When we speak of free software, we are referring to freedom, not |
| 23 | +price. Our General Public Licenses are designed to make sure that you |
| 24 | +have the freedom to distribute copies of free software (and charge for |
| 25 | +this service if you wish), that you receive source code or can get it |
| 26 | +if you want it, that you can change the software or use pieces of it |
| 27 | +in new free programs; and that you know you can do these things. |
| 28 | + |
| 29 | + To protect your rights, we need to make restrictions that forbid |
| 30 | +anyone to deny you these rights or to ask you to surrender the rights. |
| 31 | +These restrictions translate to certain responsibilities for you if you |
| 32 | +distribute copies of the software, or if you modify it. |
| 33 | + |
| 34 | + For example, if you distribute copies of such a program, whether |
| 35 | +gratis or for a fee, you must give the recipients all the rights that |
| 36 | +you have. You must make sure that they, too, receive or can get the |
| 37 | +source code. And you must show them these terms so they know their |
| 38 | +rights. |
| 39 | + |
| 40 | + We protect your rights with two steps: (1) copyright the software, and |
| 41 | +(2) offer you this license which gives you legal permission to copy, |
| 42 | +distribute and/or modify the software. |
| 43 | + |
| 44 | + Also, for each author's protection and ours, we want to make certain |
| 45 | +that everyone understands that there is no warranty for this free |
| 46 | +software. If the software is modified by someone else and passed on, we |
| 47 | +want its recipients to know that what they have is not the original, so |
| 48 | +that any problems introduced by others will not reflect on the original |
| 49 | +authors' reputations. |
| 50 | + |
| 51 | + Finally, any free program is threatened constantly by software |
| 52 | +patents. We wish to avoid the danger that redistributors of a free |
| 53 | +program will individually obtain patent licenses, in effect making the |
| 54 | +program proprietary. To prevent this, we have made it clear that any |
| 55 | +patent must be licensed for everyone's free use or not licensed at all. |
| 56 | + |
| 57 | + The precise terms and conditions for copying, distribution and |
| 58 | +modification follow. |
| 59 | + |
| 60 | + GNU GENERAL PUBLIC LICENSE |
| 61 | + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
| 62 | + |
| 63 | + 0. This License applies to any program or other work which contains |
| 64 | +a notice placed by the copyright holder saying it may be distributed |
| 65 | +under the terms of this General Public License. The "Program", below, |
| 66 | +refers to any such program or work, and a "work based on the Program" |
| 67 | +means either the Program or any derivative work under copyright law: |
| 68 | +that is to say, a work containing the Program or a portion of it, |
| 69 | +either verbatim or with modifications and/or translated into another |
| 70 | +language. (Hereinafter, translation is included without limitation in |
| 71 | +the term "modification".) Each licensee is addressed as "you". |
| 72 | + |
| 73 | +Activities other than copying, distribution and modification are not |
| 74 | +covered by this License; they are outside its scope. The act of |
| 75 | +running the Program is not restricted, and the output from the Program |
| 76 | +is covered only if its contents constitute a work based on the |
| 77 | +Program (independent of having been made by running the Program). |
| 78 | +Whether that is true depends on what the Program does. |
| 79 | + |
| 80 | + 1. You may copy and distribute verbatim copies of the Program's |
| 81 | +source code as you receive it, in any medium, provided that you |
| 82 | +conspicuously and appropriately publish on each copy an appropriate |
| 83 | +copyright notice and disclaimer of warranty; keep intact all the |
| 84 | +notices that refer to this License and to the absence of any warranty; |
| 85 | +and give any other recipients of the Program a copy of this License |
| 86 | +along with the Program. |
| 87 | + |
| 88 | +You may charge a fee for the physical act of transferring a copy, and |
| 89 | +you may at your option offer warranty protection in exchange for a fee. |
| 90 | + |
| 91 | + 2. You may modify your copy or copies of the Program or any portion |
| 92 | +of it, thus forming a work based on the Program, and copy and |
| 93 | +distribute such modifications or work under the terms of Section 1 |
| 94 | +above, provided that you also meet all of these conditions: |
| 95 | + |
| 96 | + a) You must cause the modified files to carry prominent notices |
| 97 | + stating that you changed the files and the date of any change. |
| 98 | + |
| 99 | + b) You must cause any work that you distribute or publish, that in |
| 100 | + whole or in part contains or is derived from the Program or any |
| 101 | + part thereof, to be licensed as a whole at no charge to all third |
| 102 | + parties under the terms of this License. |
| 103 | + |
| 104 | + c) If the modified program normally reads commands interactively |
| 105 | + when run, you must cause it, when started running for such |
| 106 | + interactive use in the most ordinary way, to print or display an |
| 107 | + announcement including an appropriate copyright notice and a |
| 108 | + notice that there is no warranty (or else, saying that you provide |
| 109 | + a warranty) and that users may redistribute the program under |
| 110 | + these conditions, and telling the user how to view a copy of this |
| 111 | + License. (Exception: if the Program itself is interactive but |
| 112 | + does not normally print such an announcement, your work based on |
| 113 | + the Program is not required to print an announcement.) |
| 114 | + |
| 115 | +These requirements apply to the modified work as a whole. If |
| 116 | +identifiable sections of that work are not derived from the Program, |
| 117 | +and can be reasonably considered independent and separate works in |
| 118 | +themselves, then this License, and its terms, do not apply to those |
| 119 | +sections when you distribute them as separate works. But when you |
| 120 | +distribute the same sections as part of a whole which is a work based |
| 121 | +on the Program, the distribution of the whole must be on the terms of |
| 122 | +this License, whose permissions for other licensees extend to the |
| 123 | +entire whole, and thus to each and every part regardless of who wrote it. |
| 124 | + |
| 125 | +Thus, it is not the intent of this section to claim rights or contest |
| 126 | +your rights to work written entirely by you; rather, the intent is to |
| 127 | +exercise the right to control the distribution of derivative or |
| 128 | +collective works based on the Program. |
| 129 | + |
| 130 | +In addition, mere aggregation of another work not based on the Program |
| 131 | +with the Program (or with a work based on the Program) on a volume of |
| 132 | +a storage or distribution medium does not bring the other work under |
| 133 | +the scope of this License. |
| 134 | + |
| 135 | + 3. You may copy and distribute the Program (or a work based on it, |
| 136 | +under Section 2) in object code or executable form under the terms of |
| 137 | +Sections 1 and 2 above provided that you also do one of the following: |
| 138 | + |
| 139 | + a) Accompany it with the complete corresponding machine-readable |
| 140 | + source code, which must be distributed under the terms of Sections |
| 141 | + 1 and 2 above on a medium customarily used for software interchange; or, |
| 142 | + |
| 143 | + b) Accompany it with a written offer, valid for at least three |
| 144 | + years, to give any third party, for a charge no more than your |
| 145 | + cost of physically performing source distribution, a complete |
| 146 | + machine-readable copy of the corresponding source code, to be |
| 147 | + distributed under the terms of Sections 1 and 2 above on a medium |
| 148 | + customarily used for software interchange; or, |
| 149 | + |
| 150 | + c) Accompany it with the information you received as to the offer |
| 151 | + to distribute corresponding source code. (This alternative is |
| 152 | + allowed only for noncommercial distribution and only if you |
| 153 | + received the program in object code or executable form with such |
| 154 | + an offer, in accord with Subsection b above.) |
| 155 | + |
| 156 | +The source code for a work means the preferred form of the work for |
| 157 | +making modifications to it. For an executable work, complete source |
| 158 | +code means all the source code for all modules it contains, plus any |
| 159 | +associated interface definition files, plus the scripts used to |
| 160 | +control compilation and installation of the executable. However, as a |
| 161 | +special exception, the source code distributed need not include |
| 162 | +anything that is normally distributed (in either source or binary |
| 163 | +form) with the major components (compiler, kernel, and so on) of the |
| 164 | +operating system on which the executable runs, unless that component |
| 165 | +itself accompanies the executable. |
| 166 | + |
| 167 | +If distribution of executable or object code is made by offering |
| 168 | +access to copy from a designated place, then offering equivalent |
| 169 | +access to copy the source code from the same place counts as |
| 170 | +distribution of the source code, even though third parties are not |
| 171 | +compelled to copy the source along with the object code. |
| 172 | + |
| 173 | + 4. You may not copy, modify, sublicense, or distribute the Program |
| 174 | +except as expressly provided under this License. Any attempt |
| 175 | +otherwise to copy, modify, sublicense or distribute the Program is |
| 176 | +void, and will automatically terminate your rights under this License. |
| 177 | +However, parties who have received copies, or rights, from you under |
| 178 | +this License will not have their licenses terminated so long as such |
| 179 | +parties remain in full compliance. |
| 180 | + |
| 181 | + 5. You are not required to accept this License, since you have not |
| 182 | +signed it. However, nothing else grants you permission to modify or |
| 183 | +distribute the Program or its derivative works. These actions are |
| 184 | +prohibited by law if you do not accept this License. Therefore, by |
| 185 | +modifying or distributing the Program (or any work based on the |
| 186 | +Program), you indicate your acceptance of this License to do so, and |
| 187 | +all its terms and conditions for copying, distributing or modifying |
| 188 | +the Program or works based on it. |
| 189 | + |
| 190 | + 6. Each time you redistribute the Program (or any work based on the |
| 191 | +Program), the recipient automatically receives a license from the |
| 192 | +original licensor to copy, distribute or modify the Program subject to |
| 193 | +these terms and conditions. You may not impose any further |
| 194 | +restrictions on the recipients' exercise of the rights granted herein. |
| 195 | +You are not responsible for enforcing compliance by third parties to |
| 196 | +this License. |
| 197 | + |
| 198 | + 7. If, as a consequence of a court judgment or allegation of patent |
| 199 | +infringement or for any other reason (not limited to patent issues), |
| 200 | +conditions are imposed on you (whether by court order, agreement or |
| 201 | +otherwise) that contradict the conditions of this License, they do not |
| 202 | +excuse you from the conditions of this License. If you cannot |
| 203 | +distribute so as to satisfy simultaneously your obligations under this |
| 204 | +License and any other pertinent obligations, then as a consequence you |
| 205 | +may not distribute the Program at all. For example, if a patent |
| 206 | +license would not permit royalty-free redistribution of the Program by |
| 207 | +all those who receive copies directly or indirectly through you, then |
| 208 | +the only way you could satisfy both it and this License would be to |
| 209 | +refrain entirely from distribution of the Program. |
| 210 | + |
| 211 | +If any portion of this section is held invalid or unenforceable under |
| 212 | +any particular circumstance, the balance of the section is intended to |
| 213 | +apply and the section as a whole is intended to apply in other |
| 214 | +circumstances. |
| 215 | + |
| 216 | +It is not the purpose of this section to induce you to infringe any |
| 217 | +patents or other property right claims or to contest validity of any |
| 218 | +such claims; this section has the sole purpose of protecting the |
| 219 | +integrity of the free software distribution system, which is |
| 220 | +implemented by public license practices. Many people have made |
| 221 | +generous contributions to the wide range of software distributed |
| 222 | +through that system in reliance on consistent application of that |
| 223 | +system; it is up to the author/donor to decide if he or she is willing |
| 224 | +to distribute software through any other system and a licensee cannot |
| 225 | +impose that choice. |
| 226 | + |
| 227 | +This section is intended to make thoroughly clear what is believed to |
| 228 | +be a consequence of the rest of this License. |
| 229 | + |
| 230 | + 8. If the distribution and/or use of the Program is restricted in |
| 231 | +certain countries either by patents or by copyrighted interfaces, the |
| 232 | +original copyright holder who places the Program under this License |
| 233 | +may add an explicit geographical distribution limitation excluding |
| 234 | +those countries, so that distribution is permitted only in or among |
| 235 | +countries not thus excluded. In such case, this License incorporates |
| 236 | +the limitation as if written in the body of this License. |
| 237 | + |
| 238 | + 9. The Free Software Foundation may publish revised and/or new versions |
| 239 | +of the General Public License from time to time. Such new versions will |
| 240 | +be similar in spirit to the present version, but may differ in detail to |
| 241 | +address new problems or concerns. |
| 242 | + |
| 243 | +Each version is given a distinguishing version number. If the Program |
| 244 | +specifies a version number of this License which applies to it and "any |
| 245 | +later version", you have the option of following the terms and conditions |
| 246 | +either of that version or of any later version published by the Free |
| 247 | +Software Foundation. If the Program does not specify a version number of |
| 248 | +this License, you may choose any version ever published by the Free Software |
| 249 | +Foundation. |
| 250 | + |
| 251 | + 10. If you wish to incorporate parts of the Program into other free |
| 252 | +programs whose distribution conditions are different, write to the author |
| 253 | +to ask for permission. For software which is copyrighted by the Free |
| 254 | +Software Foundation, write to the Free Software Foundation; we sometimes |
| 255 | +make exceptions for this. Our decision will be guided by the two goals |
| 256 | +of preserving the free status of all derivatives of our free software and |
| 257 | +of promoting the sharing and reuse of software generally. |
| 258 | + |
| 259 | + NO WARRANTY |
| 260 | + |
| 261 | + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
| 262 | +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
| 263 | +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
| 264 | +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
| 265 | +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 266 | +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
| 267 | +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
| 268 | +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
| 269 | +REPAIR OR CORRECTION. |
| 270 | + |
| 271 | + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
| 272 | +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
| 273 | +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
| 274 | +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
| 275 | +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
| 276 | +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
| 277 | +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
| 278 | +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
| 279 | +POSSIBILITY OF SUCH DAMAGES. |
| 280 | + |
| 281 | + END OF TERMS AND CONDITIONS |
| 282 | + |
| 283 | + How to Apply These Terms to Your New Programs |
| 284 | + |
| 285 | + If you develop a new program, and you want it to be of the greatest |
| 286 | +possible use to the public, the best way to achieve this is to make it |
| 287 | +free software which everyone can redistribute and change under these terms. |
| 288 | + |
| 289 | + To do so, attach the following notices to the program. It is safest |
| 290 | +to attach them to the start of each source file to most effectively |
| 291 | +convey the exclusion of warranty; and each file should have at least |
| 292 | +the "copyright" line and a pointer to where the full notice is found. |
| 293 | + |
| 294 | + <one line to give the program's name and a brief idea of what it does.> |
| 295 | + Copyright (C) <year> <name of author> |
| 296 | + |
| 297 | + This program is free software; you can redistribute it and/or modify |
| 298 | + it under the terms of the GNU General Public License as published by |
| 299 | + the Free Software Foundation; either version 2 of the License, or |
| 300 | + (at your option) any later version. |
| 301 | + |
| 302 | + This program is distributed in the hope that it will be useful, |
| 303 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 304 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 305 | + GNU General Public License for more details. |
| 306 | + |
| 307 | + You should have received a copy of the GNU General Public License along |
| 308 | + with this program; if not, write to the Free Software Foundation, Inc., |
| 309 | + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 310 | + |
| 311 | +Also add information on how to contact you by electronic and paper mail. |
| 312 | + |
| 313 | +If the program is interactive, make it output a short notice like this |
| 314 | +when it starts in an interactive mode: |
| 315 | + |
| 316 | + Gnomovision version 69, Copyright (C) year name of author |
| 317 | + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
| 318 | + This is free software, and you are welcome to redistribute it |
| 319 | + under certain conditions; type `show c' for details. |
| 320 | + |
| 321 | +The hypothetical commands `show w' and `show c' should show the appropriate |
| 322 | +parts of the General Public License. Of course, the commands you use may |
| 323 | +be called something other than `show w' and `show c'; they could even be |
| 324 | +mouse-clicks or menu items--whatever suits your program. |
| 325 | + |
| 326 | +You should also get your employer (if you work as a programmer) or your |
| 327 | +school, if any, to sign a "copyright disclaimer" for the program, if |
| 328 | +necessary. Here is a sample; alter the names: |
| 329 | + |
| 330 | + Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
| 331 | + `Gnomovision' (which makes passes at compilers) written by James Hacker. |
| 332 | + |
| 333 | + <signature of Ty Coon>, 1 April 1989 |
| 334 | + Ty Coon, President of Vice |
| 335 | + |
| 336 | +This General Public License does not permit incorporating your program into |
| 337 | +proprietary programs. If your program is a subroutine library, you may |
| 338 | +consider it more useful to permit linking proprietary applications with the |
| 339 | +library. If this is what you want to do, use the GNU Lesser General |
| 340 | +Public License instead of this License. |
Index: trunk/extensions/TradeTrack/TradeTrack.sql |
— | — | @@ -0,0 +1,67 @@ |
| 2 | +-- Store mapping of i18n key of "trademark" to an ID |
| 3 | +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/tradetrack_trademarks ( |
| 4 | + -- Trademark Id |
| 5 | + tt_mark_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, |
| 6 | + -- Text (i18n key) for rating description |
| 7 | + tt_mark varchar(255) binary NOT NULL |
| 8 | +) /*$wgDBTableOptions*/; |
| 9 | + |
| 10 | +-- Default trademarks |
| 11 | +INSERT INTO /*$wgDBprefix*/tradetrack_trademarks (tt_mark) VALUES |
| 12 | + ('wmf'), |
| 13 | + ('wikipedia'), |
| 14 | + ('wiktionary'), |
| 15 | + ('wikiquote'), |
| 16 | + ('wikibooks'), |
| 17 | + ('wikiversity'), |
| 18 | + ('wikispecies'), |
| 19 | + ('wikisource'), |
| 20 | + ('mediawiki'), |
| 21 | + ('wikimediacommons'), |
| 22 | + ('wikimediaincubator'), |
| 23 | + ('wikinews'), |
| 24 | + ('other') /*$wgDBTableOptions*/; |
| 25 | + |
| 26 | +-- Store request data |
| 27 | +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/tradetrack_requests ( |
| 28 | + -- Request Id |
| 29 | + tt_request_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, |
| 30 | + -- This defines the purpose type flag (commercial, non-commercial, media) |
| 31 | + tt_purpose VARCHAR(200) NOT NULL DEFAULT "", |
| 32 | + -- This defines whether or not there is an existing agreement in place |
| 33 | + tt_agreement VARCHAR(200) NOT NULL DEFAULT "", |
| 34 | + -- Store the provided name |
| 35 | + tt_name VARCHAR(200) NOT NULL, |
| 36 | + -- Store the provided email |
| 37 | + tt_email VARCHAR(200) NOT NULL, |
| 38 | + -- Store the provided organization name |
| 39 | + tt_orgname VARCHAR(200) NOT NULL, |
| 40 | + -- Store the value set for "other" if selected |
| 41 | + tt_otherval VARCHAR(200) NULL, |
| 42 | + -- Store the phone number |
| 43 | + tt_phone VARCHAR(200) NOT NULL, |
| 44 | + -- MW Timestamp |
| 45 | + tt_timestamp BINARY(14) NOT NULL DEFAULT '', |
| 46 | + -- This stores the text describing how the marks will be used. |
| 47 | + tt_usage TEXT NOT NULL, |
| 48 | + -- This stores the user's mailing address. It probably doesn't need to be this large. |
| 49 | + tt_mailingaddress TEXT NOT NULL |
| 50 | +) /*$wgDBTableOptions*/; |
| 51 | + |
| 52 | +-- Store individual mark data |
| 53 | +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/tradetrack_mark_requests ( |
| 54 | + -- Foreign key to tradetrack_requests.tt_request_id |
| 55 | + tt_request_id INT UNSIGNED NOT NULL, |
| 56 | + -- Foreign key to tradetrack_trademarks.tt_mark_id |
| 57 | + tt_mark_id INT UNSIGNED NOT NULL, |
| 58 | + -- MW Timestamp |
| 59 | + tt_timestamp BINARY(14) NOT NULL DEFAULT '', |
| 60 | + |
| 61 | + PRIMARY KEY (tt_request_id, tt_mark_id, tt_timestamp) |
| 62 | +) /*$wgDBTableOptions*/; |
| 63 | +CREATE INDEX /*i*/tt_mark_connection ON /*_*/tradetrack_mark_requests (tt_request_id); |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | + |
Index: trunk/extensions/TradeTrack/images/errormark.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/TradeTrack/images/errormark.gif |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 69 | + application/octet-stream |
Index: trunk/extensions/TradeTrack/images/question.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/TradeTrack/images/question.gif |
___________________________________________________________________ |
Added: svn:mime-type |
2 | 70 | + application/octet-stream |
Index: trunk/extensions/TradeTrack/images/question-hover.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/TradeTrack/images/question-hover.gif |
___________________________________________________________________ |
Added: svn:mime-type |
3 | 71 | + application/octet-stream |
Index: trunk/extensions/TradeTrack/images/tipsy.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/TradeTrack/images/tipsy.gif |
___________________________________________________________________ |
Added: svn:mime-type |
4 | 72 | + application/octet-stream |
Index: trunk/extensions/TradeTrack/images/arrow.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/TradeTrack/images/arrow.gif |
___________________________________________________________________ |
Added: svn:mime-type |
5 | 73 | + application/octet-stream |
Index: trunk/extensions/TradeTrack/TradeTrack.i18n.php |
— | — | @@ -0,0 +1,147 @@ |
| 2 | +<?php |
| 3 | +$messages = array(); |
| 4 | + |
| 5 | +/** English |
| 6 | + * @author Brandon Harris |
| 7 | + */ |
| 8 | +$messages['en'] = array( |
| 9 | + 'tradetrack-desc' => 'Trade Track, a tool for tracking Wikimedia trademark requests', |
| 10 | + 'tradetrack-header' => 'Requests to use Wikimedia trademarks', |
| 11 | + 'tradetrack-all-fields-required' => 'All fields are required.', |
| 12 | + 'tradetrack-overview' => "Although the user-generated content of Wikimedia projects are generally licensed through open-source licensing schemes such as Creative Commons, the same is not true of Wikimedia trademarks and word marks. The Wikimedia Foundation owns all Wikimedia trademarks, logos, and word marks associated with Wikimedia projects, and use of that content without the Foundation's permission is prohibited. |
| 13 | + If you or the agency you represent would like to use a word mark or trademarked logo owned by the Wikimedia Foundation, please submit a request using the form below.", |
| 14 | + 'tradetrack-purpose-question' => 'For what purpose will the trademark be used?', |
| 15 | + 'tradetrack-purpose-label-commercial' => 'Commercial', |
| 16 | + 'tradetrack-purpose-expanse-commercial' => '(for-profit)', |
| 17 | + 'tradetrack-purpose-label-noncommercial' => 'Non-commercial', |
| 18 | + 'tradetrack-purpose-expanse-noncommercial' => '(non-profit or educational)', |
| 19 | + 'tradetrack-purpose-label-media' => 'Media', |
| 20 | + 'tradetrack-purpose-expanse-media' => '(incidental use in TV, film, or other media)', |
| 21 | + 'tradetrack-usage-label' => 'Please describe how you will use the trademark', |
| 22 | + 'tradetrack-usage-expanse' => "Will it be used online? As part of a product or service incorporating Wikimedia content? To promote another product? For journalism or commentary?", |
| 23 | + 'tradetrack-logo-which' => "Which word mark or trademarked logo do you want to use?", |
| 24 | + 'tradetrack-which-wmf' => 'Wikimedia Foundation', |
| 25 | + 'tradetrack-which-wikipedia' => 'Wikipedia', |
| 26 | + 'tradetrack-which-wiktionary' => 'Wiktionary', |
| 27 | + 'tradetrack-which-wikiquote' => 'Wikiquote', |
| 28 | + 'tradetrack-which-wikibooks' => 'Wikibooks', |
| 29 | + 'tradetrack-which-wikiversity' => 'Wikiversity', |
| 30 | + 'tradetrack-which-wikispecies' => 'Wikispecies', |
| 31 | + 'tradetrack-which-wikisource' => 'Wikisource', |
| 32 | + 'tradetrack-which-mediawiki' => 'Mediawiki', |
| 33 | + 'tradetrack-which-wikimediacommons' => 'Wikimedia Commons', |
| 34 | + 'tradetrack-which-wikimediaincubator' => 'Wikimedia Incubator', |
| 35 | + 'tradetrack-which-wikinews' => 'Wikinews', |
| 36 | + 'tradetrack-which-other' => 'Other', |
| 37 | + 'tradetrack-about-label-mailingaddress' => 'Mailing address', |
| 38 | + 'tradetrack-about-expanse-mailingaddress' => "Please provide contact information where we can follow up with your request. Remember to include your country!", |
| 39 | + 'tradetrack-about-label-yourname' => 'Your name', |
| 40 | + 'tradetrack-about-label-orgname' => "Your organization's name", |
| 41 | + 'tradetrack-about-expanse-orgname' => 'The name of the entity that will use the Wikimedia trademark.', |
| 42 | + 'tradetrack-about-label-email' => 'Email address', |
| 43 | + 'tradetrack-about-expanse-email' => 'Your primary email address', |
| 44 | + 'tradetrack-about-label-confirmemail' => 'Email address confirmation', |
| 45 | + 'tradetrack-about-expanse-confirmemail' => 'Type your primary email address again', |
| 46 | + 'tradetrack-about-label-phone' => 'Phone number', |
| 47 | + 'tradetrack-statement-label' => 'Statement of Good Faith', |
| 48 | + 'tradetrack-statement-expanse' => "By checking the box below, I hereby swear or affirm under penalty of perjury that I am the authorized representative of the organization or person named above, and that I completed this form accurately, in good faith, and to the best of my ability.", |
| 49 | + 'tradetrack-statement-checkboxlabel' => 'I swear or affirm', |
| 50 | + 'tradetrack-characters-remaining-notice' => 'Characters Remaining', |
| 51 | + 'tradetrack-button-continue' => 'Continue', |
| 52 | + 'tradetrack-button-back' => 'Back', |
| 53 | + 'tradetrack-button-submit' => 'Submit', |
| 54 | + 'tradetrack-nonprofit-preexisting-agreement-question' => 'If you are operating a non-profit organization, do you have a preexisting agreement or contract with the Wikimedia Foundation?', |
| 55 | + 'tradetrack-nonprofit-preexisting-agreement-yes' => 'Yes, I am a non-profit organization with a preexisting relationship with Wikimedia.', |
| 56 | + 'tradetrack-nonprofit-preexisting-agreement-no-unaffilliated' => 'No, I am a non-profit organization unaffiliated with Wikimedia.', |
| 57 | + 'tradetrack-nonprofit-preexisting-agreement-no-mistake' => 'No. And I made a mistake; I am NOT a non-profit organization.', |
| 58 | + 'tradetrack-thanks-header' => 'Thank You', |
| 59 | + 'tradetrack-thanks-text' => 'Thank you for your interest. Your request has been submitted and will be routed to the correct person for review.', |
| 60 | + 'tradetrack-errors-have-happened' => 'One or more errors have occurred. Please correct them below.', |
| 61 | + 'tradetrack-errors-pacman-death' => 'An unknown error has occurred. Please start again.', |
| 62 | + 'tradetrack-errors-no-route' => 'You must select which type of request you are making.', |
| 63 | + 'tradetrack-errors-invalid-route' => 'The type of request supplied is invalid.', |
| 64 | + 'tradetrack-errors-noncom-no-selection' => 'You must select one of the available agreement types.', |
| 65 | + 'tradetrack-errors-noncom-invalid-selection' => 'The agreement type provided is invalid.', |
| 66 | + 'tradetrack-errors-zero-marks' => "You haven't selected any logos or trademarks.", |
| 67 | + 'tradetrack-errors-other-set-but-not-checked' => 'You have entered a value for "other" but did not select it.', |
| 68 | + 'tradetrack-errors-missing-other-value' => 'You selected "other" but did not provide a value for it.', |
| 69 | + 'tradetrack-errors-other-too-long' => 'The value supplied for "other" is too long. The maximum length for this field is $1 characters.', |
| 70 | + 'tradetrack-errors-generic-empty' => 'This field is required.', |
| 71 | + 'tradetrack-errors-generic-too-long' => 'The value supplied for this field is too long. The maximum length allowed is $1 characters.', |
| 72 | + 'tradetrack-errors-emails-do-not-match' => 'The email addresses supplied do not match.', |
| 73 | + 'tradetrack-errors-email-fails-regex' => 'The email address supplied is invalid. Please provide a valid email address.', |
| 74 | + 'tradetrack-errors-no-accept-statement' => 'You must agree to the Statement of Good Faith.', |
| 75 | +); |
| 76 | + |
| 77 | +/** Message documentation (Message documentation) |
| 78 | + * @author Brandon Harris |
| 79 | + */ |
| 80 | +$messages['qqq'] = array( |
| 81 | + 'tradetrack-desc' => 'Trade Track, a tool for tracking Wikimedia trademark requests', |
| 82 | + 'tradetrack-header' => 'Header for (most) pages', |
| 83 | + 'tradetrack-all-fields-required' => 'Indicates that all form elements are required.', |
| 84 | + 'tradetrack-overview' => 'Describes the purpose of the special page to the user.', |
| 85 | + 'tradetrack-purpose-question' => 'Asks the user for their primary purpose for the trademark usage', |
| 86 | + 'tradetrack-purpose-label-commercial' => 'Term for commercial focused usages', |
| 87 | + 'tradetrack-purpose-expanse-commercial' => 'Provides more information about what constitutes a commercial purpose', |
| 88 | + 'tradetrack-purpose-label-noncommercial' => 'Term for non-commercial focused usages', |
| 89 | + 'tradetrack-purpose-expanse-noncommercial' => 'Provides more information about what constitutes a non-commercial purpose', |
| 90 | + 'tradetrack-purpose-label-media' => 'Term for media-focused usages (e.g., television, movies)', |
| 91 | + 'tradetrack-purpose-expanse-media' => 'Provides more information about what constitutes a media purpose', |
| 92 | + 'tradetrack-usage-label' => 'Asks how the user will use the trademark', |
| 93 | + 'tradetrack-usage-expanse' => "Gives further clarification as to what the tradetrack-usage-label question means", |
| 94 | + 'tradetrack-logo-which' => "Asks which logo or logos the user wishes to use.", |
| 95 | + // These are all trademark terms owned by the foundation. |
| 96 | + 'tradetrack-which-wmf' => 'Wikimedia Foundation', |
| 97 | + 'tradetrack-which-wikipedia' => 'Wikipedia', |
| 98 | + 'tradetrack-which-wiktionary' => 'Wiktionary', |
| 99 | + 'tradetrack-which-wikiquote' => 'Wikiquote', |
| 100 | + 'tradetrack-which-wikibooks' => 'Wikibooks', |
| 101 | + 'tradetrack-which-wikiversity' => 'Wikiversity', |
| 102 | + 'tradetrack-which-wikispecies' => 'Wikispecies', |
| 103 | + 'tradetrack-which-wikisource' => 'Wikisource', |
| 104 | + 'tradetrack-which-mediawiki' => 'Mediawiki', |
| 105 | + 'tradetrack-which-wikimediacommons' => 'Wikimedia Commons', |
| 106 | + 'tradetrack-which-wikimediaincubator' => 'Wikimedia Incubator', |
| 107 | + 'tradetrack-which-wikinews' => 'Wikinews', |
| 108 | + // End terms |
| 109 | + 'tradetrack-which-other' => 'This is a label in case the user wishes to utilize a mark not listed', |
| 110 | + 'tradetrack-about-label-mailingaddress' => 'Label for the mailing address field', |
| 111 | + 'tradetrack-about-expanse-mailingaddress' => "More information about the mailing address field.", |
| 112 | + 'tradetrack-about-label-yourname' => "Label for the user's name field", |
| 113 | + 'tradetrack-about-label-orgname' => "Label for the user's organization's field", |
| 114 | + 'tradetrack-about-expanse-orgname' => 'More information about the organization name field.', |
| 115 | + 'tradetrack-about-label-email' => "Label for the user's email address field", |
| 116 | + 'tradetrack-about-expanse-email' => 'More information about the email address field', |
| 117 | + 'tradetrack-about-label-confirmemail' => "Label for confirming the user's email field", |
| 118 | + 'tradetrack-about-expanse-confirmemail' => 'Describes a bit why we want a confirmation email.', |
| 119 | + 'tradetrack-about-label-phone' => "Label for the user's phone number field", |
| 120 | + 'tradetrack-statement-label' => 'Label for the statement of good faith section.', |
| 121 | + 'tradetrack-statement-expanse' => "This is a legal statement. If translated, there should be a pointer to the English version.", |
| 122 | + 'tradetrack-statement-checkboxlabel' => 'Indicates that the user agrees with the statement', |
| 123 | + 'tradetrack-characters-remaining-notice' => "This is part of a user interface element that counts remaining characters in a specific field. The number of characters is handled through code, and it appears as 'XX Characters Remaining'", |
| 124 | + 'tradetrack-button-continue' => 'This button indicates moving forward to the next step', |
| 125 | + 'tradetrack-button-back' => 'This button indicates heading backwards.', |
| 126 | + 'tradetrack-button-submit' => 'This button indicates submitting.', |
| 127 | + 'tradetrack-nonprofit-preexisting-agreement-question' => 'This asks a question as to whether or not the user has an existing agreement with the WMF.', |
| 128 | + 'tradetrack-nonprofit-preexisting-agreement-yes' => 'Indicates that the user organization has an existing agreement with the WMF', |
| 129 | + 'tradetrack-nonprofit-preexisting-agreement-no-unaffilliated' => 'Indicates that the user does not have an existing agreement with the WMF', |
| 130 | + 'tradetrack-nonprofit-preexisting-agreement-no-mistake' => 'Indicates that the user does not have an agreement, and needs to go back to the previous screen.', |
| 131 | + 'tradetrack-thanks-header' => 'A header for the final success screen', |
| 132 | + 'tradetrack-thanks-text' => 'Text that thanks the user for submitting a request', |
| 133 | + 'tradetrack-errors-have-happened' => 'A generic error message that tells the user that one or more errors have occurred and that they should be addressed below.', |
| 134 | + 'tradetrack-errors-pacman-death' => 'A catch-all error string for a *fatal*, unrecoverable error.', |
| 135 | + 'tradetrack-errors-no-route' => 'Error indicating that the user must select a purpose for their request.', |
| 136 | + 'tradetrack-errors-invalid-route' => 'Error indicating that the purpose provided was invalid', |
| 137 | + 'tradetrack-errors-noncom-no-selection' => 'Error indicating that the user must select whether or not they have a non-commercial agreement.', |
| 138 | + 'tradetrack-errors-noncom-invalid-selection' => 'Error indicating that the non-commercial agreement type is invalid.', |
| 139 | + 'tradetrack-errors-zero-marks' => "Error indicating that the user hasn't selected any trademarks for use.", |
| 140 | + 'tradetrack-errors-other-set-but-not-checked' => 'Error indicating that the user entered a value for "other" but did not check the box.', |
| 141 | + 'tradetrack-errors-missing-other-value' => 'Error indicating that the user selected the "other" value but did not provide any data for it.', |
| 142 | + 'tradetrack-errors-other-too-long' => 'Error indicating that the field in question has gone over maximum length. This message is specifically keyed to the "other" value in the marks list.', |
| 143 | + 'tradetrack-errors-generic-empty' => 'Error indicating that a field is required.', |
| 144 | + 'tradetrack-errors-generic-too-long' => 'Error indicating that the field in question has gone over maximum length.', |
| 145 | + 'tradetrack-errors-emails-do-not-match' => 'Error indicatingt that the email addresses supplied do not match.', |
| 146 | + 'tradetrack-errors-email-fails-regex' => 'Error indicating that the email address supplied is invalid.', |
| 147 | + 'tradetrack-errors-no-accept-statement' => 'Error informing the user that they must agree to the statement of good faith', |
| 148 | +); |
Index: trunk/extensions/TradeTrack/css/TradeTrack.css |
— | — | @@ -0,0 +1,92 @@ |
| 2 | +#tradetrack-screens { |
| 3 | + margin: 1em auto 1em auto; |
| 4 | + padding: 10px; |
| 5 | + width:500px; |
| 6 | + background: #EEEEEE; |
| 7 | +} |
| 8 | +#tradetrack-screens input[type='text'], #tradetrack-screens textarea { |
| 9 | + width: 70%; |
| 10 | + margin-left: 10px; |
| 11 | +} |
| 12 | +#tradetrack-screens textarea { |
| 13 | + margin-bottom: 0px; |
| 14 | +} |
| 15 | +.characters-remaining-box { display: none; } |
| 16 | +html > body #tradetrack-screens .characters-remaining-box { |
| 17 | + display:block; |
| 18 | + margin-top: -5px; |
| 19 | + width: 70%; |
| 20 | + margin-left: 10px; |
| 21 | + text-align: right; |
| 22 | + font-size: 0.8em; |
| 23 | + color: #4d4d4d; |
| 24 | +} |
| 25 | +#tradetrack-screens .characters-remaining-box .tradetrack-toomany { |
| 26 | + color: #a31205; |
| 27 | +} |
| 28 | +div.tradetrack-element, div.tradetrack-element-error { |
| 29 | + padding: 5px; |
| 30 | + margin-bottom: 5px; |
| 31 | +} |
| 32 | + |
| 33 | +div.tradetrack-element { |
| 34 | + border: 1px solid #EEEEEE; |
| 35 | +} |
| 36 | +div.tradetrack-element-error { |
| 37 | + border: 1px solid #a91100; |
| 38 | +} |
| 39 | +div.tradetrack-button-box { |
| 40 | + text-align: right; |
| 41 | +} |
| 42 | +.tradetrack-button { |
| 43 | +} |
| 44 | +.tradetrack-question-expanse { |
| 45 | + font-size: 0.8em; |
| 46 | +} |
| 47 | +#tradetrack-screens ul.tradetrack-element-list { |
| 48 | + margin-left: 20px; |
| 49 | + list-style: none; |
| 50 | + list-style-image: none; |
| 51 | + list-style-type: none; |
| 52 | +} |
| 53 | +.tradetrack-element-list li { |
| 54 | + list-style-type: none; |
| 55 | +} |
| 56 | +.tradetrack-errornotice { |
| 57 | + margin: 1em auto 1em auto; |
| 58 | + padding: 5px; |
| 59 | + background: #e8e8e8; |
| 60 | + border: 2px solid #a91100; |
| 61 | +} |
| 62 | +ul.tradetrack-errors { |
| 63 | + margin-left: 10px; |
| 64 | + list-style-type: none; |
| 65 | + color: #a91100; |
| 66 | + list-style-image: none; |
| 67 | +} |
| 68 | +ul.tradetrack-errors li { |
| 69 | + list-style-type: none; |
| 70 | +} |
| 71 | +label.tradetrack-question-label { |
| 72 | + font-weight: bold; |
| 73 | + float: left; |
| 74 | +} |
| 75 | +.tradetrack-field-hint { |
| 76 | + width: 11px; |
| 77 | + height: 24px; |
| 78 | + display: block; |
| 79 | + float: left; |
| 80 | + margin-left: 5px; |
| 81 | + margin-top: -3px; |
| 82 | + background: url(../images/question.gif) 0 50% no-repeat; |
| 83 | +} |
| 84 | +.tradetrack-field-hint:hover { |
| 85 | + background: url(../images/question-hover.gif) 0 50% no-repeat; |
| 86 | +} |
| 87 | +/* Tipsy Styles */ |
| 88 | +.tipsy { padding: 5px 5px 10px; font-size: 12px; position: absolute; z-index: 100000; overflow: visible; } |
| 89 | +.tipsy-inner { padding: 5px 8px 4px 8px; background-color: #d6f3ff; color: black; border: 1px solid #5dc9f4; max-width: 300px; text-align: left; } |
| 90 | +.tipsy-arrow { position: absolute; background: url( '../images/arrow.gif' ) no-repeat top left; width: 13px; height: 13px; } |
| 91 | +.tipsy-se .tipsy-arrow { bottom: -2px; right: 10px; background-position: 0% 100%; } |
| 92 | + |
| 93 | +/* End Tipsy styles */ |
Index: trunk/extensions/TradeTrack/TradeTrack.php |
— | — | @@ -0,0 +1,30 @@ |
| 2 | +<?php |
| 3 | +// Process system for managing trademark usage requests. |
| 4 | + |
| 5 | +$wgExtensionCredits['specialpage'][] = array( |
| 6 | + 'path' => __FILE__, |
| 7 | + 'name' => 'Trade Track', |
| 8 | + 'author' => array( 'Brandon Harris' ), |
| 9 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:TradeTrack', |
| 10 | + 'descriptionmsg' => 'tradetrack-desc', |
| 11 | +); |
| 12 | + |
| 13 | +$wgSpecialPages['TradeTrack'] = 'SpecialTradeTrack'; |
| 14 | + |
| 15 | +$wgTradeTrackEmailSubject = "A new Trademark Request has Arrived"; |
| 16 | +$wgTradeTrackFromEmail = "tradetrack@wikimedia.org"; |
| 17 | + |
| 18 | +$wgAutoloadClasses['SpecialTradeTrack'] = dirname(__FILE__) . "/SpecialTradeTrack.php"; |
| 19 | +$wgAutoloadClasses['TradeTrackScreen'] = dirname(__FILE__) . "/templates/TradeTrackScreen.php"; |
| 20 | +$wgAutoloadClasses['TradeTrackScreenDetailsForm'] = dirname(__FILE__) . "/templates/TradeTrackScreenDetailsForm.php"; |
| 21 | +$wgAutoloadClasses['TradeTrackScreenNonComAgreement'] = dirname(__FILE__) . "/templates/TradeTrackScreenNonComAgreement.php"; |
| 22 | +$wgAutoloadClasses['TradeTrackScreenRouting'] = dirname(__FILE__) . "/templates/TradeTrackScreenRouting.php"; |
| 23 | +$wgAutoloadClasses['TradeTrackScreenThanks'] = dirname(__FILE__) . "/templates/TradeTrackScreenThanks.php"; |
| 24 | +$wgAutoloadClasses['TradeTrackEmail'] = dirname(__FILE__) . "/templates/TradeTrackEmail.php"; |
| 25 | + |
| 26 | +$wgExtensionMessagesFiles['TradeTrack'] = dirname( __FILE__ ) . "/TradeTrack.i18n.php"; |
| 27 | + |
| 28 | +$wgTradeTrackEmailCommercial = "bharris@wikimedia.org"; // Who gets commercial requests (Kul) |
| 29 | +$wgTradeTrackEmailNonCommercial = "bharris@wikimedia.org"; // Who gets non-commercial requests (Mike) |
| 30 | +$wgTradeTrackEmailMedia = "bharris@wikimedia.org"; // Who gets media requests (Jay) |
| 31 | + |
Index: trunk/extensions/TradeTrack/SpecialTradeTrack.php |
— | — | @@ -0,0 +1,591 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class SpecialTradeTrack extends SpecialPage { |
| 5 | + |
| 6 | + |
| 7 | + /** |
| 8 | + * This is an array of the various trademarks that we're watching over. |
| 9 | + */ |
| 10 | + private static $TRADEMARK_LIST = array( |
| 11 | + 'wmf', |
| 12 | + 'wikipedia', |
| 13 | + 'wiktionary', |
| 14 | + 'wikiquote', |
| 15 | + 'wikibooks', |
| 16 | + 'wikiversity', |
| 17 | + 'wikispecies', |
| 18 | + 'wikisource', |
| 19 | + 'mediawiki', |
| 20 | + 'wikimediacommons', |
| 21 | + 'wikimediaincubator', |
| 22 | + 'wikinews', |
| 23 | + 'other', |
| 24 | + ); |
| 25 | + |
| 26 | + /** |
| 27 | + * This defines the prefix for (most) all of our form field elements |
| 28 | + */ |
| 29 | + private static $VARIABLE_PREFIX = "tradetrack-elements-"; |
| 30 | + |
| 31 | + /** |
| 32 | + * This is our validation framework array. It is requied by validateField(), |
| 33 | + * below. |
| 34 | + * |
| 35 | + * For each field that we are going to validate, we need an entry in the |
| 36 | + * array. That entry will contain two additional arrays: 'errmsgs' and |
| 37 | + * 'tests'. |
| 38 | + * |
| 39 | + * The tests array defines each test type for the field and |
| 40 | + * possible thresholds or arguments to the test (e.g., max length). |
| 41 | + * |
| 42 | + * The errmsgs array has named entries for the each test and defines which |
| 43 | + * message string should be shoved into the errors field if the test fails. |
| 44 | + * |
| 45 | + * This could probably better be handled with a single array set, thus: |
| 46 | + * |
| 47 | + * $fieldname => array( |
| 48 | + * 'testname' => array( |
| 49 | + * 'threshold' => $value, |
| 50 | + * 'error' => $value, |
| 51 | + * ), |
| 52 | + * ); |
| 53 | + * I will probably refactor to that but want to get it working first. |
| 54 | + * |
| 55 | + * I would have loved to use a constant here but that threw some |
| 56 | + * errors so I have to use the real number. |
| 57 | + */ |
| 58 | + private static $VALIDATION_FIELDS = array( |
| 59 | + 'usage' => array( |
| 60 | + 'errmsgs' => array( |
| 61 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 62 | + 'required' => 'tradetrack-errors-generic-empty', |
| 63 | + ), |
| 64 | + 'tests' => array( |
| 65 | + 'max' => 5000, |
| 66 | + 'required' => true |
| 67 | + ), |
| 68 | + ), |
| 69 | + 'mailingaddress' => array( |
| 70 | + 'errmsgs' => array( |
| 71 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 72 | + 'required' => 'tradetrack-errors-generic-empty', |
| 73 | + ), |
| 74 | + 'tests' => array( |
| 75 | + 'max' => 5000, |
| 76 | + 'required' => true |
| 77 | + ), |
| 78 | + ), |
| 79 | + 'name' => array( |
| 80 | + 'errmsgs' => array( |
| 81 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 82 | + 'required' => 'tradetrack-errors-generic-empty', |
| 83 | + ), |
| 84 | + 'tests' => array( |
| 85 | + 'max' => 200, |
| 86 | + 'required' => true |
| 87 | + ), |
| 88 | + ), |
| 89 | + 'orgname' => array( |
| 90 | + 'errmsgs' => array( |
| 91 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 92 | + 'required' => 'tradetrack-errors-generic-empty', |
| 93 | + ), |
| 94 | + 'tests' => array( |
| 95 | + 'max' => 200, |
| 96 | + 'required' => true |
| 97 | + ), |
| 98 | + ), |
| 99 | + 'email' => array( |
| 100 | + 'errmsgs' => array( |
| 101 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 102 | + 'required' => 'tradetrack-errors-generic-empty', |
| 103 | + 'equals' => 'tradetrack-errors-emails-do-not-match' |
| 104 | + ), |
| 105 | + 'tests' => array( |
| 106 | + 'max' => 200, |
| 107 | + 'required' => true, |
| 108 | + 'equals' => 'confirmemail' |
| 109 | + ), |
| 110 | + ), |
| 111 | + 'confirmemail' => array( |
| 112 | + 'errmsgs' => array( |
| 113 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 114 | + 'required' => 'tradetrack-errors-generic-empty', |
| 115 | + ), |
| 116 | + 'tests' => array( |
| 117 | + 'max' => 200, |
| 118 | + 'required' => true |
| 119 | + ), |
| 120 | + ), |
| 121 | + 'phone' => array( |
| 122 | + 'errmsgs' => array( |
| 123 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 124 | + 'required' => 'tradetrack-errors-generic-empty', |
| 125 | + ), |
| 126 | + 'tests' => array( |
| 127 | + 'max' => 200, |
| 128 | + 'required' => true |
| 129 | + ), |
| 130 | + ), |
| 131 | + 'statementagreement' => array( |
| 132 | + 'errmsgs' => array( |
| 133 | + 'required' => 'tradetrack-errors-no-accept-statement', |
| 134 | + ), |
| 135 | + 'tests' => array( |
| 136 | + 'required' => true |
| 137 | + ), |
| 138 | + ), |
| 139 | + 'otherval' => array( |
| 140 | + 'errmsgs' => array( |
| 141 | + 'max' => 'tradetrack-errors-generic-too-long', |
| 142 | + 'requiredif' => 'tradetrack-errors-missing-other-value', |
| 143 | + 'emptyunless' => 'tradetrack-errors-other-set-but-not-checked', |
| 144 | + ), |
| 145 | + 'tests' => array( |
| 146 | + 'max' => 200, |
| 147 | + 'requiredif' => 'tradetrack-which-other', |
| 148 | + 'emptyunless' => 'tradetrack-which-other', |
| 149 | + ), |
| 150 | + ), |
| 151 | + ); |
| 152 | + |
| 153 | + /** |
| 154 | + * Some private arrays to point to our resources. |
| 155 | + */ |
| 156 | + private static $styleFiles = array( |
| 157 | + array( 'src' => 'css/TradeTrack', 'version' => 1 ), |
| 158 | + ); |
| 159 | + |
| 160 | + private static $scriptFiles = array( |
| 161 | + array( 'src' => 'js/TradeTrack.js', 'version' => 1 ), |
| 162 | + array( 'src' => 'js/jquery.tipsy.js', 'version' => 1 ), |
| 163 | + array( 'src' => 'js/jquery.NobleCount.js', 'version' => 1 ), |
| 164 | + ); |
| 165 | + |
| 166 | + private static $messages = array(); |
| 167 | + private static $scripts = array(); |
| 168 | + |
| 169 | + /** |
| 170 | + * This is our errors array. |
| 171 | + */ |
| 172 | + private $errors = array(); |
| 173 | + |
| 174 | + function __construct() { |
| 175 | + parent::__construct( 'TradeTrack' ); |
| 176 | + wfLoadExtensionMessages( 'TradeTrack' ); |
| 177 | + } |
| 178 | + |
| 179 | + /** |
| 180 | + * Adds an error to the local error stack for later display. The local errors array is |
| 181 | + * actually a matrix where each "key" points to another array. |
| 182 | + * |
| 183 | + * Note that we need to be adding *parsed* error messages here. Why? Because there isn't an easy |
| 184 | + * way to send $1, $2, etc. down the pipe and into the templates. |
| 185 | + * |
| 186 | + * @param target The named target for the error (a single target can have multiple errors) |
| 187 | + * @param errorString The message to throw into the error. This should be an i18n pointer. |
| 188 | + */ |
| 189 | + function addError($target, $errorString) { |
| 190 | + $eList = $errorsArray[$target]; |
| 191 | + if (!$eList) { $eList = array( ); } |
| 192 | + array_push($eList, $errorString); |
| 193 | + |
| 194 | + $this->errors[$target] = $eList; |
| 195 | + } |
| 196 | + |
| 197 | + /** |
| 198 | + * Simply returns true or false if there have been errors thrown during the run |
| 199 | + * |
| 200 | + * @return true if there are errors; false otherwise. |
| 201 | + */ |
| 202 | + function hasErrors() { |
| 203 | + if ( count( $this->errors ) != 0 ) { return true; } |
| 204 | + return false; |
| 205 | + } |
| 206 | + |
| 207 | + |
| 208 | + function execute( $par ) { |
| 209 | + global $wgRequest, $wgOut; |
| 210 | + |
| 211 | + global $wgExtensionAssetsPath; |
| 212 | + |
| 213 | + foreach ( self::$scriptFiles as $script ) { |
| 214 | + $wgOut->addScriptFile( $wgExtensionAssetsPath . "/TradeTrack/{$script['src']}", $script['version'] ); |
| 215 | + } |
| 216 | + |
| 217 | + foreach ( self::$styleFiles as $style ) { |
| 218 | + $wgOut->addExtensionStyle( $wgExtensionAssetsPath . "/TradeTrack/{$style['src']}?{$style['version']}" ); |
| 219 | + } |
| 220 | + |
| 221 | + |
| 222 | + $wgOut->setPageTitle( wfMsg( 'tradetrack-header' ) ); |
| 223 | + |
| 224 | + // This is our template data array. |
| 225 | + $tData = array(); |
| 226 | + $tData['formURL'] = $this->getTitle()->getLinkURL( $query ); |
| 227 | + |
| 228 | + // First, see if it's supplied from the page. |
| 229 | + $doaction = $wgRequest->getVal( 'doaction' ); |
| 230 | + |
| 231 | + |
| 232 | + $success = false; |
| 233 | + |
| 234 | + // open wide. |
| 235 | + ob_start(); |
| 236 | + |
| 237 | + |
| 238 | + switch( $doaction ) { |
| 239 | + case 'route': |
| 240 | + /* |
| 241 | + * The user has selected (or failed to select) the first step on their way to Mordor. |
| 242 | + * Are we going overland, or through the Mines of Moria? |
| 243 | + */ |
| 244 | + $purpose = $wgRequest->getVal( 'tradetrack-purpose' ); |
| 245 | + if ( !isset( $purpose ) ) { |
| 246 | + $this->addError( 'tradetrack-purpose', wfMsg( 'tradetrack-errors-no-route' ) ); |
| 247 | + } else if ( ( $purpose != 'Commercial' ) |
| 248 | + && ( $purpose != 'Non-Commercial' ) |
| 249 | + && ( $purpose != 'Media' ) ) { |
| 250 | + $this->addError( 'tradetrack-purpose', wfMsg( 'tradetrack-errors-invalid-route' ) ); |
| 251 | + } |
| 252 | + |
| 253 | + if ( $this->hasErrors() ) { |
| 254 | + $tmp = new TradeTrackScreenRouting(); |
| 255 | + } else { |
| 256 | + $tData['purpose'] = $purpose; |
| 257 | + if ( $purpose == 'Non-Commercial' ) { |
| 258 | + $tmp = new TradeTrackScreenNonComAgreement(); |
| 259 | + } else { |
| 260 | + $tmp = new TradeTrackScreenDetailsForm(); |
| 261 | + } |
| 262 | + } |
| 263 | + break; |
| 264 | + case 'noncomroute': |
| 265 | + /* |
| 266 | + * Over land it is. |
| 267 | + * This is an interleave screen, only available if you select "Non-Commercial." |
| 268 | + * This is mostly for data collection. |
| 269 | + * The user will still be forced to deal with the Orks in Moria. |
| 270 | + */ |
| 271 | + $purpose = $wgRequest->getVal( 'tradetrack-purpose' ); |
| 272 | + if ( !isset( $purpose ) ) { |
| 273 | + // Ensure we still know what we're doing. If not, bail with the wah-wah sound. |
| 274 | + $this->addError( 'global', wfMsg( 'tradetrack-errors-pacman-death' ) ); |
| 275 | + $tmp = new TradeTrackScreenRouting(); |
| 276 | + break; |
| 277 | + } |
| 278 | + |
| 279 | + $tData['purpose'] = $purpose; |
| 280 | + |
| 281 | + $agreementType = $wgRequest-> getVal( 'tradetrack-elements-agreement' ); |
| 282 | + if ( !isset( $agreementType ) ) { |
| 283 | + $this->addError( 'tradetrack-elements-agreement', wfMsg( 'tradetrack-errors-noncom-no-selection' ) ); |
| 284 | + } else if ( ( $agreementType != 'Yes' ) |
| 285 | + && ( $agreementType != 'No' ) |
| 286 | + && ( $agreementType != 'Mistake' ) ) { |
| 287 | + $this->addError( 'tradetrack-elements-agreement', wfMsg( 'tradetrack-errors-noncom-invalid-selection' ) ); |
| 288 | + } |
| 289 | + if ( $this->hasErrors() ) { |
| 290 | + // Oh no! The thing in the lake grabbed Frodo! |
| 291 | + $tmp = new TradeTrackScreenNonComAgreement(); |
| 292 | + } else if ( $agreementType == 'Mistake' ) { |
| 293 | + // For completeness' sake, we must give the user an escape route. |
| 294 | + // Frodo decides to ditch the entire process and marry some poor hobbit back |
| 295 | + // in the Shire. |
| 296 | + $tmp = new TradeTrackScreenRouting(); |
| 297 | + } else { |
| 298 | + // Why yes, I do know the Elvish word for "Friend". |
| 299 | + // No errors of any kind, we're going in. |
| 300 | + $tData['agreementType'] = $agreementType; |
| 301 | + $tmp = new TradeTrackScreenDetailsForm(); |
| 302 | + } |
| 303 | + break; |
| 304 | + case 'details': |
| 305 | + /* |
| 306 | + * This is the final screen. This has several fields, all of which are required. |
| 307 | + * |
| 308 | + * You are in a maze of twisty passages, all alike. You may be eaten by a Balrog. |
| 309 | + */ |
| 310 | + |
| 311 | + $purpose = $wgRequest->getVal( 'tradetrack-purpose' ); |
| 312 | + if ( !isset( $purpose ) ) { |
| 313 | + // Ensure we still know what we're doing. If not, bail with the wah-wah sound. |
| 314 | + $this->addError( 'global', wfMsg( 'tradetrack-errors-pacman-death' ) ); |
| 315 | + $tmp = new TradeTrackScreenRouting(); |
| 316 | + break; |
| 317 | + } |
| 318 | + $tData['purpose'] = $purpose; |
| 319 | + |
| 320 | + // Handle lost agreement type, if required. |
| 321 | + $agreementType = $wgRequest-> getVal( 'tradetrack-elements-agreement' ); |
| 322 | + if ( ( !$agreementType) && ( $purpose == 'Non-Commercial' ) ) { |
| 323 | + $this->addError( 'global', wfMsg( 'tradetrack-errors-pacman-death' ) ); |
| 324 | + $tmp = new TradeTrackScreenRouting(); |
| 325 | + break; |
| 326 | + } |
| 327 | + $tData['agreementType'] = $agreementType; |
| 328 | + |
| 329 | + // Let's get the easy fields out of the way first. |
| 330 | + |
| 331 | + |
| 332 | + $checkElements = array( |
| 333 | + 'usage', |
| 334 | + 'mailingaddress', |
| 335 | + 'name', |
| 336 | + 'orgname', |
| 337 | + 'email', |
| 338 | + 'confirmemail', |
| 339 | + 'phone', |
| 340 | + 'statementagreement', |
| 341 | + 'otherval' |
| 342 | + ); |
| 343 | + |
| 344 | + |
| 345 | + // This runs validation on the bulk of our fields. |
| 346 | + foreach ( $checkElements as $e ) { |
| 347 | + $this->validateField( $e, $wgRequest ); |
| 348 | + $tData[$e] = $wgRequest->getVal(self::$VARIABLE_PREFIX . $e); // Shove into template data array |
| 349 | + } |
| 350 | + |
| 351 | + |
| 352 | + // Now we cycle through the trademarks list and see if any of them are set. |
| 353 | + $tData['trademarks'] = array(); |
| 354 | + |
| 355 | + foreach ( self::$TRADEMARK_LIST as $property ) { |
| 356 | + if ( $wgRequest->getBool( "tradetrack-which-$property" ) ) { |
| 357 | + $tData['trademarks'][$property] = $property; |
| 358 | + } |
| 359 | + } |
| 360 | + |
| 361 | + if ( count( $tData['trademarks'] ) == 0 ) { |
| 362 | + // Didn't select a single mark |
| 363 | + $this->addError( 'tradetrack-element-list', wfMsg( 'tradetrack-errors-zero-marks' ) ); |
| 364 | + } |
| 365 | + |
| 366 | + |
| 367 | + // Now, if errors, kick back. |
| 368 | + if ( $this->hasErrors() ) { |
| 369 | + // Still stuck in the mines. |
| 370 | + $tmp = new TradeTrackScreenDetailsForm(); |
| 371 | + } else { |
| 372 | + // Yay! Now we get to frolic with the Elves. |
| 373 | + $success = true; |
| 374 | + $tmp = new TradeTrackScreenThanks(); |
| 375 | + } |
| 376 | + |
| 377 | + break; |
| 378 | + default: |
| 379 | + /* |
| 380 | + * This is the first time to the page, or there has been some sort of |
| 381 | + * unrecoverable error. Ladies and gentlemen, I give you the first screen. |
| 382 | + */ |
| 383 | + $tmp = new TradeTrackScreenRouting(); |
| 384 | + break; |
| 385 | + } |
| 386 | + |
| 387 | + if ( ( isset( $tmp ) ) && ( $tmp instanceof QuickTemplate ) ) { |
| 388 | + |
| 389 | + // Stick the trademark list into the template's data space. |
| 390 | + $tData['TRADEMARK_LIST'] = self::$TRADEMARK_LIST; |
| 391 | + |
| 392 | + // Add in spices. |
| 393 | + $tmp->set( 'tData', $tData ); |
| 394 | + $tmp->set( 'errors', $this->errors ); |
| 395 | + |
| 396 | + // Bake at 300 degrees for 20 minutes. |
| 397 | + $tmp->execute(); |
| 398 | + } |
| 399 | + |
| 400 | + $wgOut->addHtml( ob_get_clean() ); |
| 401 | + |
| 402 | + if ( $success ) { |
| 403 | + |
| 404 | + // Change the page title |
| 405 | + $wgOut->setPageTitle( wfMsg( 'tradetrack-thanks-header' ) ); |
| 406 | + |
| 407 | + |
| 408 | + // Insert to the database. |
| 409 | + $this->insertTradeTrackRequest( $tData ); |
| 410 | + |
| 411 | + // Now build the email |
| 412 | + global $wgTradeTrackEmailCommercial; |
| 413 | + global $wgTradeTrackEmailNonCommercial; |
| 414 | + global $wgTradeTrackEmailMedia; |
| 415 | + global $wgTradeTrackEmailSubject; |
| 416 | + global $wgTradeTrackFromEmail; |
| 417 | + |
| 418 | + $toEmail = ""; |
| 419 | + |
| 420 | + // Who gets the email? |
| 421 | + switch ( $tData['purpose'] ) { |
| 422 | + case 'Commercial': |
| 423 | + $toEmail = $wgTradeTrackEmailCommercial; |
| 424 | + break; |
| 425 | + case 'Non-Commercial': |
| 426 | + $toEmail = $wgTradeTrackEmailNonCommercial; |
| 427 | + break; |
| 428 | + case 'Media': |
| 429 | + $toEmail = $wgTradeTrackEmailMedia; |
| 430 | + break; |
| 431 | + default: |
| 432 | + $toEmail = $wgTradeTrackEmailNonCommercial; |
| 433 | + break; |
| 434 | + } |
| 435 | + |
| 436 | + ob_start(); |
| 437 | + |
| 438 | + $emailTmp = new TradeTrackEmail(); |
| 439 | + $emailTmp->set( 'tData', $tData ); |
| 440 | + $emailTmp->execute(); |
| 441 | + $generatedEmail = ob_get_clean(); |
| 442 | + $mailer = new UserMailer(); |
| 443 | + |
| 444 | + $mailer->send( new MailAddress( $toEmail ) , new MailAddress( $wgTradeTrackFromEmail ), $wgTradeTrackEmailSubject, $generatedEmail); |
| 445 | + |
| 446 | + // debug line to dump this to the end screen. |
| 447 | + $wgOut->addHtml( $generatedEmail ); |
| 448 | + |
| 449 | + |
| 450 | + } |
| 451 | + |
| 452 | + } |
| 453 | + |
| 454 | + /** |
| 455 | + * This does field validation. It looks up fields in the VALIDATION_FIELDS array |
| 456 | + * and runs tests on them. This, combined with VALIDATION_FIELDS, is really a |
| 457 | + * crude validation framework. |
| 458 | + * |
| 459 | + * Entries in the VALIDATION_FIELDS array must be named the same as the field in the |
| 460 | + * html form, *minus* the value of $VARIABLE_PREFIX. |
| 461 | + * |
| 462 | + * This method takes the $wgRequest object as a variable rather than the possible |
| 463 | + * value supplied by the form. The reason for this is that one of the tests is |
| 464 | + * "equals", which makes sure two form values are the same (e.g., email and |
| 465 | + * emailconfirm). |
| 466 | + * |
| 467 | + * This method *also* takes the supplied values and sticks them back into the |
| 468 | + * page's global "data" array, so that they can be redisplayed if there are errors. |
| 469 | + * |
| 470 | + * This could (should) probably be pulled out into a separate class. |
| 471 | + * |
| 472 | + * @param fieldName the name of the form field to validate |
| 473 | + * @param $request the $wgRequest object. |
| 474 | + */ |
| 475 | + function validateField( $fieldName, $request ) { |
| 476 | + |
| 477 | + $value = $request->getVal( self::$VARIABLE_PREFIX . $fieldName ); |
| 478 | + |
| 479 | + // No need to validate. This field has no tests. |
| 480 | + if ( !isset ( self::$VALIDATION_FIELDS[$fieldName] ) ) { |
| 481 | + return true; |
| 482 | + } |
| 483 | + |
| 484 | + foreach ( self::$VALIDATION_FIELDS[$fieldName]['tests'] as $vType => $vThreshold ) { |
| 485 | + |
| 486 | + switch ( $vType ) { |
| 487 | + case 'max': |
| 488 | + // Tests that the value does not exceed a threshold, defined in the array (max => threshold) |
| 489 | + if ( ( isset( $value ) ) && ( strlen( $value ) > $vThreshold ) ) { |
| 490 | + $this->addError( "tradetrack-elements-$fieldName", wfMsg( self::$VALIDATION_FIELDS[$fieldName]['errmsgs'][$vType], array( $vThreshold ) ) ); |
| 491 | + } |
| 492 | + break; |
| 493 | + case 'required': |
| 494 | + // Tests to ensure that the value exists. |
| 495 | + if ( !$value ) { |
| 496 | + $this->addError( "tradetrack-elements-$fieldName", wfMsg( self::$VALIDATION_FIELDS[$fieldName]['errmsgs'][$vType] ) ); |
| 497 | + } |
| 498 | + break; |
| 499 | + case 'requiredif': |
| 500 | + // This field is only required if another field is set as well. |
| 501 | + // Note that we do NOT use variable prefix here. |
| 502 | + $required = $request->getVal( $vThreshold ); |
| 503 | + if ( ( !$value ) && ( isset( $required ) ) ) { |
| 504 | + $this->addError( "tradetrack-elements-$fieldName", wfMsg( self::$VALIDATION_FIELDS[$fieldName]['errmsgs'][$vType] ) ); |
| 505 | + } |
| 506 | + break; |
| 507 | + case 'emptyunless': |
| 508 | + // This field should be empty unless another field is set. |
| 509 | + $unless = $request->getVal( $vThreshold ); |
| 510 | + if ( ( $value ) && ( !isset( $unless ) ) ) { |
| 511 | + $this->addError( "tradetrack-elements-$fieldName", wfMsg( self::$VALIDATION_FIELDS[$fieldName]['errmsgs'][$vType] ) ); |
| 512 | + } |
| 513 | + break; |
| 514 | + case 'equals': |
| 515 | + // Tests that the field value is equal to the value of another feild ('equals' => comparison field) |
| 516 | + if ( isset( $value ) ) { |
| 517 | + $compare = $request->getVal( self::$VARIABLE_PREFIX . $vThreshold ); |
| 518 | + if ( ( !isset( $compare ) ) || ( $value !== $compare ) ) { |
| 519 | + $this->addError( "tradetrack-elements-$fieldName", wfMsg( self::$VALIDATION_FIELDS[$fieldName]['errmsgs'][$vType] ) ); |
| 520 | + } |
| 521 | + } |
| 522 | + break; |
| 523 | + default: |
| 524 | + break; |
| 525 | + } |
| 526 | + } |
| 527 | + return true; |
| 528 | + } |
| 529 | + |
| 530 | + |
| 531 | + function sendEmailMail( array $tData ) { |
| 532 | + |
| 533 | + |
| 534 | + } |
| 535 | + |
| 536 | + |
| 537 | + private function insertTradeTrackRequest( array $tData ) { |
| 538 | + $dbw = wfGetDB( DB_MASTER ); |
| 539 | + |
| 540 | + // Ugly. |
| 541 | + $markMapping = array(); |
| 542 | + |
| 543 | + $res = $dbw->select( |
| 544 | + 'tradetrack_trademarks', |
| 545 | + array ('tt_mark_id', 'tt_mark') |
| 546 | + ); |
| 547 | + foreach ( $res as $row ) { |
| 548 | + $markMapping[$row->tt_mark] = $row->tt_mark_id; |
| 549 | + } |
| 550 | + |
| 551 | + $timestamp = $dbw->timestamp(); |
| 552 | + |
| 553 | + $dbw->insert( |
| 554 | + 'tradetrack_requests', |
| 555 | + array( |
| 556 | + 'tt_purpose' => $tData['purpose'], |
| 557 | + 'tt_agreement' => $tData['agreementType'], |
| 558 | + 'tt_name' => $tData['name'], |
| 559 | + 'tt_email' => $tData['email'], |
| 560 | + 'tt_orgname' => $tData['orgname'], |
| 561 | + 'tt_otherval' => $tData['otherval'], |
| 562 | + 'tt_phone' => $tData['phone'], |
| 563 | + 'tt_usage' => $tData['usage'], |
| 564 | + 'tt_mailingaddress' => $tData['mailingaddress'], |
| 565 | + 'tt_timestamp' => $timestamp, |
| 566 | + ), |
| 567 | + __METHOD__, |
| 568 | + array( 'IGNORE' ) |
| 569 | + ); |
| 570 | + |
| 571 | + $lastId = $dbw->insertId(); |
| 572 | + // Now we insert rows for every mark requested. |
| 573 | + |
| 574 | + foreach ( $tData['trademarks'] as $trademark ) { |
| 575 | + $dbw->insert( |
| 576 | + 'tradetrack_mark_requests', |
| 577 | + array( |
| 578 | + 'tt_request_id' => $lastId, |
| 579 | + 'tt_mark_id' => $markMapping[$trademark], |
| 580 | + 'tt_timestamp' => $timestamp, |
| 581 | + ), |
| 582 | + __METHOD__, |
| 583 | + array( 'IGNORE' ) |
| 584 | + ); |
| 585 | + |
| 586 | + } |
| 587 | + |
| 588 | + |
| 589 | + } |
| 590 | + |
| 591 | + |
| 592 | +} |
Index: trunk/extensions/TradeTrack/js/TradeTrack.js |
— | — | @@ -0,0 +1,31 @@ |
| 2 | +( function( $ ) { |
| 3 | + $.TradeTrack = { |
| 4 | + |
| 5 | + 'fn' : { |
| 6 | + 'init': function( $$options ) { |
| 7 | + $j( '.tradetrack-field-hint' ).tipsy( { gravity : 'se', opacity: '0.9' } ); |
| 8 | + $j( '#tradetrack-elements-usage-textarea' ).NobleCount('#tradetrack-elements-usage-count', { |
| 9 | + max_chars: 5000, |
| 10 | + on_positive: function(t_obj, char_area, c_settings, char_rem){ |
| 11 | + $(char_area).removeClass( 'tradetrack-toomany' ); |
| 12 | + }, |
| 13 | + on_negative: function(t_obj, char_area, c_settings, char_rem){ |
| 14 | + $(char_area).addClass( 'tradetrack-toomany' ); |
| 15 | + } |
| 16 | + }); |
| 17 | + $j( '#tradetrack-elements-mailingaddress-textarea' ).NobleCount('#tradetrack-elements-mailingaddress-count', { |
| 18 | + max_chars: 5000, |
| 19 | + on_positive: function(t_obj, char_area, c_settings, char_rem){ |
| 20 | + $(char_area).removeClass( 'tradetrack-toomany' ); |
| 21 | + }, |
| 22 | + on_negative: function(t_obj, char_area, c_settings, char_rem){ |
| 23 | + $(char_area).addClass( 'tradetrack-toomany' ); |
| 24 | + } |
| 25 | + }); |
| 26 | + }, |
| 27 | + } |
| 28 | + }; |
| 29 | + $( document ).ready( function () { |
| 30 | + $.TradeTrack.fn.init( ); |
| 31 | + } ); //document ready |
| 32 | +} )( jQuery ); |
Index: trunk/extensions/TradeTrack/js/jquery.NobleCount.js |
— | — | @@ -0,0 +1,480 @@ |
| 2 | +/****************************************************************************************************** |
| 3 | + |
| 4 | + jQuery.NobleCount |
| 5 | + |
| 6 | + Author Jeremy Horn |
| 7 | + Version 1.0 |
| 8 | + Date: 3/21/2010 |
| 9 | + |
| 10 | + Copyright (c) 2010 Jeremy Horn- jeremydhorn(at)gmail(dot)c0m | http://tpgblog.com |
| 11 | + Dual licensed under MIT and GPL. |
| 12 | + |
| 13 | + DESCRIPTION |
| 14 | + NobleCount... for a more 'proper' count of the characters remaining. |
| 15 | + |
| 16 | + NobleCount is a customizable jQuery plugin for a more the improved counting of the remaining |
| 17 | + characters, and resulting behaviors, of a text entry object, e.g. input textfield, textarea. |
| 18 | + |
| 19 | + As text is entered into the target text area an object for the purposes of tracking |
| 20 | + the total number of characters remaining, defined as the maximum number of characters |
| 21 | + minus the current total number of characters within the text entry object, and storing |
| 22 | + that information visually and/or within the DOM as an HTML 5 compliant data-* attribute. |
| 23 | + |
| 24 | + Events and CSS Class alterations, if defined, are triggered based on current user |
| 25 | + interaction with the target text entry object as well as the current state (positive or |
| 26 | + negative) of the character remaining value. |
| 27 | + |
| 28 | + NobleCount supports pre-existing text within the text object. |
| 29 | + NobleCount supports jQuery chaining. |
| 30 | + |
| 31 | + Within NobleCount context... |
| 32 | + NEGATIVE is defined as Integers < 0 |
| 33 | + POSITIVE is defined as Integers >= 0 [on_positive will fire when char_rem == 0] |
| 34 | + |
| 35 | + BY DEFAULT |
| 36 | + - maximum characters EQUAL 140 characters |
| 37 | + - no events defined |
| 38 | + - no class changes defined |
| 39 | + - no DOM attributes are created/altered |
| 40 | + - user permitted to type past the maximum number of characters limit, resulting in |
| 41 | + negative number of characters remaining |
| 42 | + |
| 43 | + IMPLEMENTATION |
| 44 | + |
| 45 | + $('#textarea1').NobleCount('#characters_remaining1'); |
| 46 | + $('#textfield2').NobleCount('#characters_remaining2', { / * OPTIONS * / }); |
| 47 | + |
| 48 | + COMPATIBILITY |
| 49 | + |
| 50 | + Tested in FF3.5, IE7 |
| 51 | + With jQuery 1.3.x, 1.4.x |
| 52 | + |
| 53 | + METHOD(S) |
| 54 | + To properly intialize, both the text entry object and the object that will store the |
| 55 | + total number of characters remaining must exist and be passed to NobleCount. |
| 56 | + |
| 57 | + $(TEXT_ENTRY_OBJECT).NobleCount(CHARACTERS_REMAINING_OBJECT); |
| 58 | + |
| 59 | + Any callback functions assigned to any of the availale events are passed the following |
| 60 | + parameters: t_obj, char_area, c_settings, char_rem |
| 61 | + |
| 62 | + t_obj text entry object |
| 63 | + |
| 64 | + char_area selection of the characters remaining object |
| 65 | + |
| 66 | + c_settings result of the options passed into NobleCount at time of |
| 67 | + initialization merged with the default options |
| 68 | + |
| 69 | + ** this is a GREAT way to pass in and remember other state |
| 70 | + information that will be needed upon the triggering of |
| 71 | + NobleCount events ** |
| 72 | + |
| 73 | + char_rem integer representation of the total number of characters |
| 74 | + remaining resulting from the calculated difference between |
| 75 | + the target maximum number of characters and the current |
| 76 | + number of characters currently within t_obj |
| 77 | + |
| 78 | + Both TEXT_ENTRY_OBJECT and CHARACTERS_REMAINING_OBJECT must be specified and valid. |
| 79 | + |
| 80 | + Upon successful initialization, all appropriate events and classes are applied to |
| 81 | + the CHARACTERS_REMAINING_OBJECT, including the storage (if not disabled) visually |
| 82 | + or only in the DOM (if enabled) of the integer representing the number of characters |
| 83 | + remaining. |
| 84 | + |
| 85 | + The target maximum number of characters (max_chars) are determined by the following |
| 86 | + precedence rules.... |
| 87 | + |
| 88 | + if max_chars passed via constructor |
| 89 | + max_chars = max_chars passed |
| 90 | + else if number exists within characters_remaining object and number > 0 |
| 91 | + max_chars = number within the text() of characters_remaining object |
| 92 | + else use the NobleCount's default max_chars |
| 93 | + |
| 94 | + CUSTOMIZATION |
| 95 | + |
| 96 | + NobleCount(c_obj, <OPTIONS>) |
| 97 | + e.g. $(t_obj).NobleCount(c_obj, {max_chars:100px}); |
| 98 | + |
| 99 | + |
| 100 | + on_negative class (STRING) or FUNCTION that is applied/called |
| 101 | + when characters remaining is negative IF DEFINED |
| 102 | + |
| 103 | + on_positive class (STRING) or FUNCTION that is applied/called |
| 104 | + when characters remaining is positive IF DEFINED |
| 105 | + |
| 106 | + on_update FUNCTION that is called when characters remaining changes |
| 107 | + |
| 108 | + max_chars target maximum number of characters |
| 109 | + |
| 110 | + block_negative if TRUE, then all attempts are made to block entering |
| 111 | + more than max_characters; not effective against user |
| 112 | + pasting in blocks of text that exceed the max_chars value |
| 113 | + otherwise, text area will let individual entering the text |
| 114 | + to exceed max_chars limit (characters remaining becomes |
| 115 | + negative) |
| 116 | + |
| 117 | + cloak: false, if TRUE, then no visual updates of characters remaining |
| 118 | + object (c_obj) will occur; this does not have any effect |
| 119 | + on the char_rem value returned via any event callbacks |
| 120 | + otherwise, the text within c_obj is constantly updated to |
| 121 | + represent the total number of characters remaining until |
| 122 | + the max_chars limit has been reached |
| 123 | + |
| 124 | + in_dom: false if TRUE and cloak is ALSO TRUE, then the number of characters |
| 125 | + remaining are stored as the attribute of c_obj |
| 126 | + named 'data-noblecount' |
| 127 | + |
| 128 | + !NOTE: if enabled, due to constant updating of a DOM element |
| 129 | + attribute user experience can appear sluggish while |
| 130 | + the individual is modifying the text entry object (t_obj) |
| 131 | + |
| 132 | + |
| 133 | + EXAMPLE OPTIONS = |
| 134 | + { |
| 135 | + on_negative: 'go_red', |
| 136 | + on_positive: 'go_green', |
| 137 | + max_chars: 25, |
| 138 | + on_update: function(t_obj, char_area, c_settings, char_rem){ |
| 139 | + if ((char_rem % 10) == 0) { |
| 140 | + char_area.css('font-weight', 'bold'); |
| 141 | + char_area.css('font-size', '300%'); |
| 142 | + } else { |
| 143 | + char_area.css('font-weight', 'normal'); |
| 144 | + char_area.css('font-size', '100%'); |
| 145 | + } |
| 146 | + } |
| 147 | + }; |
| 148 | + |
| 149 | + MORE |
| 150 | + |
| 151 | + For more details about NobleCount, its implementation, usage, and examples, go to: |
| 152 | + http://tpgblog.com/noblecount/ |
| 153 | + |
| 154 | +******************************************************************************************************/ |
| 155 | + |
| 156 | +(function($) { |
| 157 | + |
| 158 | + /********************************************************************************** |
| 159 | + |
| 160 | + FUNCTION |
| 161 | + NobleCount |
| 162 | + |
| 163 | + DESCRIPTION |
| 164 | + NobleCount method constructor |
| 165 | + |
| 166 | + allows for customization of maximum length and related update/length |
| 167 | + behaviors |
| 168 | + |
| 169 | + e.g. $(text_obj).NobleCount(characters_remaining_obj); |
| 170 | + |
| 171 | + REQUIRED: c_obj |
| 172 | + OPTIONAL: options |
| 173 | + |
| 174 | + **********************************************************************************/ |
| 175 | + |
| 176 | + $.fn.NobleCount = function(c_obj, options) { |
| 177 | + var c_settings; |
| 178 | + var mc_passed = false; |
| 179 | + |
| 180 | + // if c_obj is not specified, then nothing to do here |
| 181 | + if (typeof c_obj == 'string') { |
| 182 | + // check for new & valid options |
| 183 | + c_settings = $.extend({}, $.fn.NobleCount.settings, options); |
| 184 | + |
| 185 | + // was max_chars passed via options parameter? |
| 186 | + if (typeof options != 'undefined') { |
| 187 | + mc_passed = ((typeof options.max_chars == 'number') ? true : false); |
| 188 | + } |
| 189 | + |
| 190 | + // process all provided objects |
| 191 | + return this.each(function(){ |
| 192 | + var $this = $(this); |
| 193 | + |
| 194 | + // attach events to c_obj |
| 195 | + attach_nobility($this, c_obj, c_settings, mc_passed); |
| 196 | + }); |
| 197 | + } |
| 198 | + |
| 199 | + return this; |
| 200 | + }; |
| 201 | + |
| 202 | + |
| 203 | + /********************************************************************************** |
| 204 | + |
| 205 | + FUNCTION |
| 206 | + NobleCount.settings |
| 207 | + |
| 208 | + DESCRIPTION |
| 209 | + publically accessible data stucture containing the max_chars and |
| 210 | + event handling specifications for NobleCount |
| 211 | + |
| 212 | + can be directly accessed by '$.fn.NobleCount.settings = ... ;' |
| 213 | + |
| 214 | + **********************************************************************************/ |
| 215 | + $.fn.NobleCount.settings = { |
| 216 | + |
| 217 | + on_negative: null, // class (STRING) or FUNCTION that is applied/called |
| 218 | + // when characters remaining is negative |
| 219 | + on_positive: null, // class (STRING) or FUNCTION that is applied/called |
| 220 | + // when characters remaining is positive |
| 221 | + on_update: null, // FUNCTION that is called when characters remaining |
| 222 | + // changes |
| 223 | + max_chars: 140, // maximum number of characters |
| 224 | + block_negative: false, // if true, then all attempts are made to block entering |
| 225 | + // more than max_characters |
| 226 | + cloak: false, // if true, then no visual updates of characters |
| 227 | + // remaining (c_obj) occur |
| 228 | + in_dom: false // if true and cloak == true, then number of characters |
| 229 | + // remaining are stored as the attribute |
| 230 | + // 'data-noblecount' of c_obj |
| 231 | + |
| 232 | + }; |
| 233 | + |
| 234 | + |
| 235 | + ////////////////////////////////////////////////////////////////////////////////// |
| 236 | + |
| 237 | + // private functions and settings |
| 238 | + |
| 239 | + /********************************************************************************** |
| 240 | + |
| 241 | + FUNCTION |
| 242 | + attach_nobility |
| 243 | + |
| 244 | + DESCRIPTION |
| 245 | + performs all initialization routines and display initiation |
| 246 | + |
| 247 | + assigns both the keyup and keydown events to the target text entry |
| 248 | + object; both keyup and keydown are used to provide the smoothest |
| 249 | + user experience |
| 250 | + |
| 251 | + if max_chars_passed via constructor |
| 252 | + max_chars = max_chars_passed |
| 253 | + else if number exists within counting_object (and number > 0) |
| 254 | + max_chars = counting_object.number |
| 255 | + else use default max_chars |
| 256 | + |
| 257 | + PRE |
| 258 | + t_obj and c_obj EXIST |
| 259 | + c_settings and mc_passed initialized |
| 260 | + |
| 261 | + POST |
| 262 | + maximum number of characters for t_obj calculated and stored in max_char |
| 263 | + key events attached to t_obj |
| 264 | + |
| 265 | + **********************************************************************************/ |
| 266 | + |
| 267 | + function attach_nobility(t_obj, c_obj, c_settings, mc_passed){ |
| 268 | + var max_char = c_settings.max_chars; |
| 269 | + var char_area = $(c_obj); |
| 270 | + |
| 271 | + // first determine if max_char needs adjustment |
| 272 | + if (!mc_passed) { |
| 273 | + var tmp_num = char_area.text(); |
| 274 | + var isPosNumber = (/^[1-9]\d*$/).test(tmp_num); |
| 275 | + |
| 276 | + if (isPosNumber) { |
| 277 | + max_char = tmp_num; |
| 278 | + } |
| 279 | + } |
| 280 | + |
| 281 | + // initialize display of characters remaining |
| 282 | + // * note: initializing should not trigger on_update |
| 283 | + event_internals(t_obj, char_area, c_settings, max_char, true); |
| 284 | + |
| 285 | + // then attach the events -- seem to work better than keypress |
| 286 | + $(t_obj).keydown(function(e) { |
| 287 | + event_internals(t_obj, char_area, c_settings, max_char, false); |
| 288 | + |
| 289 | + // to block text entry, return false |
| 290 | + if (check_block_negative(e, t_obj, c_settings, max_char) == false) { |
| 291 | + return false; |
| 292 | + } |
| 293 | + }); |
| 294 | + |
| 295 | + $(t_obj).keyup(function(e) { |
| 296 | + event_internals(t_obj, char_area, c_settings, max_char, false); |
| 297 | + |
| 298 | + // to block text entry, return false |
| 299 | + if (check_block_negative(e, t_obj, c_settings, max_char) == false) { |
| 300 | + return false; |
| 301 | + } |
| 302 | + }); |
| 303 | + } |
| 304 | + |
| 305 | + |
| 306 | + /********************************************************************************** |
| 307 | + |
| 308 | + FUNCTION |
| 309 | + check_block_negative |
| 310 | + |
| 311 | + DESCRIPTION |
| 312 | + determines whether or not text entry within t_obj should be prevented |
| 313 | + |
| 314 | + PRE |
| 315 | + e EXISTS |
| 316 | + t_obj VALID |
| 317 | + c_settings and max_char initialized / calculated |
| 318 | + |
| 319 | + POST |
| 320 | + if t_obj text entry should be prevented FALSE is returned |
| 321 | + otherwise TRUE returned |
| 322 | + |
| 323 | + TODO |
| 324 | + improve selection detection and permissible behaviors experience |
| 325 | + ALSO |
| 326 | + doesnt CURRENTLY block from the pasting of large chunks of text that |
| 327 | + exceed max_char |
| 328 | + |
| 329 | + **********************************************************************************/ |
| 330 | + |
| 331 | + function check_block_negative(e, t_obj, c_settings, max_char){ |
| 332 | + if (c_settings.block_negative) { |
| 333 | + var char_code = e.which; |
| 334 | + var selected; |
| 335 | + |
| 336 | + // goofy handling required to work in both IE and FF |
| 337 | + if (typeof document.selection != 'undefined') { |
| 338 | + selected = (document.selection.createRange().text.length > 0); |
| 339 | + } else { |
| 340 | + selected = (t_obj[0].selectionStart != t_obj[0].selectionEnd); |
| 341 | + } |
| 342 | + |
| 343 | + //return false if can't write more |
| 344 | + if ((!((find_remaining(t_obj, max_char) < 1) && |
| 345 | + (char_code > 47 || char_code == 32 || char_code == 0 || char_code == 13) && |
| 346 | + !e.ctrlKey && |
| 347 | + !e.altKey && |
| 348 | + !selected)) == false) { |
| 349 | + |
| 350 | + // block text entry |
| 351 | + return false; |
| 352 | + } |
| 353 | + } |
| 354 | + |
| 355 | + // allow text entry |
| 356 | + return true; |
| 357 | + } |
| 358 | + |
| 359 | + |
| 360 | + /********************************************************************************** |
| 361 | + |
| 362 | + FUNCTION |
| 363 | + find_remaining |
| 364 | + |
| 365 | + DESCRIPTION |
| 366 | + determines of the number of characters permitted (max_char), the number of |
| 367 | + characters remaining until that limit has been reached |
| 368 | + |
| 369 | + PRE |
| 370 | + t_obj and max_char EXIST and are VALID |
| 371 | + |
| 372 | + POST |
| 373 | + returns integer of the difference between max_char and total number of |
| 374 | + characters within the text entry object (t_obj) |
| 375 | + |
| 376 | + **********************************************************************************/ |
| 377 | + |
| 378 | + function find_remaining(t_obj, max_char){ |
| 379 | + return max_char - ($(t_obj).val()).length; |
| 380 | + } |
| 381 | + |
| 382 | + |
| 383 | + /********************************************************************************** |
| 384 | + |
| 385 | + FUNCTION |
| 386 | + event_internals |
| 387 | + |
| 388 | + DESCRIPTION |
| 389 | + primarily used for the calculation of appropriate behavior resulting from |
| 390 | + any event attached to the text entry object (t_obj) |
| 391 | + |
| 392 | + whenever the char_rem and related display and/or DOM information needs |
| 393 | + updating this function is called |
| 394 | + |
| 395 | + if cloaking is being used, then no visual representation of the characters |
| 396 | + remaining, nor attempt by this plugin to change any of its visual |
| 397 | + characteristics will occur |
| 398 | + |
| 399 | + if cloaking and in_dom are both TRUE, then the number of characters |
| 400 | + remaining are stored within the HTML 5 compliant attribute of the |
| 401 | + character count remaining object (c_obj) labeled 'data-noblecount' |
| 402 | + |
| 403 | + PRE |
| 404 | + c_settings, init_disp initialized |
| 405 | + |
| 406 | + POST |
| 407 | + performs all updates to the DOM visual and otherwise required |
| 408 | + performs all relevant function calls |
| 409 | + |
| 410 | + **********************************************************************************/ |
| 411 | + |
| 412 | + function event_internals(t_obj, char_area, c_settings, max_char, init_disp) { |
| 413 | + var char_rem = find_remaining(t_obj, max_char); |
| 414 | + |
| 415 | + // is chararacters remaining positive or negative |
| 416 | + if (char_rem < 0) { |
| 417 | + toggle_states(c_settings.on_negative, c_settings.on_positive, t_obj, char_area, c_settings, char_rem); |
| 418 | + } else { |
| 419 | + toggle_states(c_settings.on_positive, c_settings.on_negative, t_obj, char_area, c_settings, char_rem); |
| 420 | + } |
| 421 | + |
| 422 | + // determine whether or not to update the text of the char_area (or c_obj) |
| 423 | + if (c_settings.cloak) { |
| 424 | + // this slows stuff down quite a bit; TODO: implement better method of publically accessible data storage |
| 425 | + if (c_settings.in_dom) { |
| 426 | + char_area.attr('data-noblecount', char_rem); |
| 427 | + } |
| 428 | + } else { |
| 429 | + // show the numbers of characters remaining |
| 430 | + char_area.text(char_rem); |
| 431 | + } |
| 432 | + |
| 433 | + // if event_internals isn't being called for initialization purposes and |
| 434 | + // on_update is a properly defined function then call it on this update |
| 435 | + if (!init_disp && jQuery.isFunction(c_settings.on_update)) { |
| 436 | + c_settings.on_update(t_obj, char_area, c_settings, char_rem); |
| 437 | + } |
| 438 | + } |
| 439 | + |
| 440 | + |
| 441 | + /********************************************************************************** |
| 442 | + |
| 443 | + FUNCTION |
| 444 | + toggle_states |
| 445 | + |
| 446 | + DESCRIPTION |
| 447 | + performs the toggling operations between the watched positive and negative |
| 448 | + characteristics |
| 449 | + |
| 450 | + first, enables/triggers/executes the toggle_on behavior/class |
| 451 | + second, disables the trigger_off class |
| 452 | + |
| 453 | + PRE |
| 454 | + toggle_on, toggle_off |
| 455 | + IF DEFINED, |
| 456 | + must be a string representation of a VALID class |
| 457 | + OR |
| 458 | + must be a VALID function |
| 459 | + |
| 460 | + POST |
| 461 | + toggle_on objects have been applied/executed |
| 462 | + toggle_off class has been removed (if it is a class) |
| 463 | + |
| 464 | + **********************************************************************************/ |
| 465 | + |
| 466 | + function toggle_states(toggle_on, toggle_off, t_obj, char_area, c_settings, char_rem){ |
| 467 | + if (toggle_on != null) { |
| 468 | + if (typeof toggle_on == 'string') { |
| 469 | + char_area.addClass(toggle_on); |
| 470 | + } else if (jQuery.isFunction(toggle_on)) { |
| 471 | + toggle_on(t_obj, char_area, c_settings, char_rem); |
| 472 | + } |
| 473 | + } |
| 474 | + |
| 475 | + if (toggle_off != null) { |
| 476 | + if (typeof toggle_off == 'string') { |
| 477 | + char_area.removeClass(toggle_off); |
| 478 | + } |
| 479 | + } |
| 480 | + } |
| 481 | +})(jQuery); |
\ No newline at end of file |
Index: trunk/extensions/TradeTrack/js/jquery.tipsy.js |
— | — | @@ -0,0 +1,202 @@ |
| 2 | +// tipsy, facebook style tooltips for jquery |
| 3 | +// version 1.0.0a |
| 4 | +// (c) 2008-2010 jason frame [jason@onehackoranother.com] |
| 5 | +// released under the MIT license |
| 6 | + |
| 7 | +(function($) { |
| 8 | + |
| 9 | + function Tipsy(element, options) { |
| 10 | + this.$element = $(element); |
| 11 | + this.options = options; |
| 12 | + this.enabled = true; |
| 13 | + this.fixTitle(); |
| 14 | + } |
| 15 | + |
| 16 | + Tipsy.prototype = { |
| 17 | + show: function() { |
| 18 | + var title = this.getTitle(); |
| 19 | + if (title && this.enabled) { |
| 20 | + var $tip = this.tip(); |
| 21 | + |
| 22 | + $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); |
| 23 | + $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity |
| 24 | + $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body); |
| 25 | + |
| 26 | + var pos = $.extend({}, this.$element.offset(), { |
| 27 | + width: this.$element[0].offsetWidth, |
| 28 | + height: this.$element[0].offsetHeight |
| 29 | + }); |
| 30 | + |
| 31 | + var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight; |
| 32 | + var gravity = (typeof this.options.gravity == 'function') |
| 33 | + ? this.options.gravity.call(this.$element[0]) |
| 34 | + : this.options.gravity; |
| 35 | + |
| 36 | + var tp; |
| 37 | + switch (gravity.charAt(0)) { |
| 38 | + case 'n': |
| 39 | + tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; |
| 40 | + break; |
| 41 | + case 's': |
| 42 | + tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; |
| 43 | + break; |
| 44 | + case 'e': |
| 45 | + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}; |
| 46 | + break; |
| 47 | + case 'w': |
| 48 | + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}; |
| 49 | + break; |
| 50 | + } |
| 51 | + |
| 52 | + if (gravity.length == 2) { |
| 53 | + if (gravity.charAt(1) == 'w') { |
| 54 | + tp.left = pos.left + pos.width / 2 - 15; |
| 55 | + } else { |
| 56 | + tp.left = pos.left + pos.width / 2 - actualWidth + 15; |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + $tip.css(tp).addClass('tipsy-' + gravity); |
| 61 | + |
| 62 | + if (this.options.fade) { |
| 63 | + $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}); |
| 64 | + } else { |
| 65 | + $tip.css({visibility: 'visible', opacity: this.options.opacity}); |
| 66 | + } |
| 67 | + } |
| 68 | + }, |
| 69 | + |
| 70 | + hide: function() { |
| 71 | + if (this.options.fade) { |
| 72 | + this.tip().stop().fadeOut(function() { $(this).remove(); }); |
| 73 | + } else { |
| 74 | + this.tip().remove(); |
| 75 | + } |
| 76 | + }, |
| 77 | + |
| 78 | + fixTitle: function() { |
| 79 | + var $e = this.$element; |
| 80 | + if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') { |
| 81 | + $e.attr('original-title', $e.attr('title') || '').removeAttr('title'); |
| 82 | + } |
| 83 | + }, |
| 84 | + |
| 85 | + getTitle: function() { |
| 86 | + var title, $e = this.$element, o = this.options; |
| 87 | + this.fixTitle(); |
| 88 | + var title, o = this.options; |
| 89 | + if (typeof o.title == 'string') { |
| 90 | + title = $e.attr(o.title == 'title' ? 'original-title' : o.title); |
| 91 | + } else if (typeof o.title == 'function') { |
| 92 | + title = o.title.call($e[0]); |
| 93 | + } |
| 94 | + title = ('' + title).replace(/(^\s*|\s*$)/, ""); |
| 95 | + return title || o.fallback; |
| 96 | + }, |
| 97 | + |
| 98 | + tip: function() { |
| 99 | + if (!this.$tip) { |
| 100 | + this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>'); |
| 101 | + } |
| 102 | + return this.$tip; |
| 103 | + }, |
| 104 | + |
| 105 | + validate: function() { |
| 106 | + if (!this.$element[0].parentNode) { |
| 107 | + this.hide(); |
| 108 | + this.$element = null; |
| 109 | + this.options = null; |
| 110 | + } |
| 111 | + }, |
| 112 | + |
| 113 | + enable: function() { this.enabled = true; }, |
| 114 | + disable: function() { this.enabled = false; }, |
| 115 | + toggleEnabled: function() { this.enabled = !this.enabled; } |
| 116 | + }; |
| 117 | + |
| 118 | + $.fn.tipsy = function(options) { |
| 119 | + |
| 120 | + if (options === true) { |
| 121 | + return this.data('tipsy'); |
| 122 | + } else if (typeof options == 'string') { |
| 123 | + var tipsy = this.data('tipsy'); |
| 124 | + if (tipsy) tipsy[options](); |
| 125 | + return this; |
| 126 | + } |
| 127 | + |
| 128 | + options = $.extend({}, $.fn.tipsy.defaults, options); |
| 129 | + |
| 130 | + function get(ele) { |
| 131 | + var tipsy = $.data(ele, 'tipsy'); |
| 132 | + if (!tipsy) { |
| 133 | + tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); |
| 134 | + $.data(ele, 'tipsy', tipsy); |
| 135 | + } |
| 136 | + return tipsy; |
| 137 | + } |
| 138 | + |
| 139 | + function enter() { |
| 140 | + var tipsy = get(this); |
| 141 | + tipsy.hoverState = 'in'; |
| 142 | + if (options.delayIn == 0) { |
| 143 | + tipsy.show(); |
| 144 | + } else { |
| 145 | + tipsy.fixTitle(); |
| 146 | + setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn); |
| 147 | + } |
| 148 | + }; |
| 149 | + |
| 150 | + function leave() { |
| 151 | + var tipsy = get(this); |
| 152 | + tipsy.hoverState = 'out'; |
| 153 | + if (options.delayOut == 0) { |
| 154 | + tipsy.hide(); |
| 155 | + } else { |
| 156 | + setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut); |
| 157 | + } |
| 158 | + }; |
| 159 | + |
| 160 | + if (!options.live) this.each(function() { get(this); }); |
| 161 | + |
| 162 | + if (options.trigger != 'manual') { |
| 163 | + var binder = options.live ? 'live' : 'bind', |
| 164 | + eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', |
| 165 | + eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; |
| 166 | + this[binder](eventIn, enter)[binder](eventOut, leave); |
| 167 | + } |
| 168 | + |
| 169 | + return this; |
| 170 | + |
| 171 | + }; |
| 172 | + |
| 173 | + $.fn.tipsy.defaults = { |
| 174 | + delayIn: 0, |
| 175 | + delayOut: 0, |
| 176 | + fade: false, |
| 177 | + fallback: '', |
| 178 | + gravity: 'n', |
| 179 | + html: false, |
| 180 | + live: false, |
| 181 | + offset: 0, |
| 182 | + opacity: 0.8, |
| 183 | + title: 'title', |
| 184 | + trigger: 'hover' |
| 185 | + }; |
| 186 | + |
| 187 | + // Overwrite this method to provide options on a per-element basis. |
| 188 | + // For example, you could store the gravity in a 'tipsy-gravity' attribute: |
| 189 | + // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); |
| 190 | + // (remember - do not modify 'options' in place!) |
| 191 | + $.fn.tipsy.elementOptions = function(ele, options) { |
| 192 | + return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; |
| 193 | + }; |
| 194 | + |
| 195 | + $.fn.tipsy.autoNS = function() { |
| 196 | + return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; |
| 197 | + }; |
| 198 | + |
| 199 | + $.fn.tipsy.autoWE = function() { |
| 200 | + return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; |
| 201 | + }; |
| 202 | + |
| 203 | +})(jQuery); |
Index: trunk/extensions/TradeTrack/README |
— | — | @@ -0,0 +1,45 @@ |
| 2 | +STATUS: |
| 3 | +====== |
| 4 | + |
| 5 | +This software is beta. There are missing features at this point. |
| 6 | + |
| 7 | +This software is specifically designed for use by the Wikimedia Foundation. |
| 8 | +It is a workflow system designed for external users to apply for the use of |
| 9 | +Wikimedia trademarks. |
| 10 | + |
| 11 | + |
| 12 | +INSTALLATION: |
| 13 | +============ |
| 14 | + |
| 15 | +1. Rename this directory to extensions/TradeTrack inside your |
| 16 | + MediaWiki directory. |
| 17 | +2. Add database tables from TradeTrack.sql using the sql.php MediaWiki tool. |
| 18 | + (On Unix, if the current directory is the MediaWiki root directory, you can |
| 19 | + say "php maintenance/sql.php extensions/TradeTrack/TradeTrack.sql".) |
| 20 | + If you haven't created the AdminSettings.php file, you will have to do that |
| 21 | + first; see http://www.mediawiki.org/wiki/Manual:AdminSettings.php |
| 22 | + Alternatively, you can run the SQL file manually (you can use the command |
| 23 | + "mysql -u $USER -p -e 'source TradeTrack.sql'" on Unix), but you might have to |
| 24 | + edit it first, and replace the /*$wgDBprefix*/ and /*$wgDBTableOptions*/ |
| 25 | + strings with the corresponding settings. |
| 26 | +3. Add this line to the end of your LocalSettings.php: |
| 27 | + require_once( "$IP/extensions/TradeTrack/TradeTrack.php" ); |
| 28 | +4. You need to define three email addresses in LocalSettings.php after that: |
| 29 | + |
| 30 | + $wgTradeTrackEmailCommercial = "foo@bar.com"; |
| 31 | + $wgTradeTrackEmailNonCommercial = "foo@bar.com"; |
| 32 | + $wgTradeTrackEmailMedia = "foo@bar.com"; |
| 33 | + |
| 34 | + |
| 35 | +CONTACT: |
| 36 | +======= |
| 37 | + |
| 38 | +* Brandon Harris |
| 39 | +* bharris@wikimedia.org |
| 40 | +* jorm in #mediawiki on irc.freenode.net |
| 41 | + |
| 42 | +CREDITS: |
| 43 | +======= |
| 44 | + |
| 45 | +Written by Brandon Harris for the Wikimedia Foundation. |
| 46 | + |
Index: trunk/extensions/TradeTrack/templates/TradeTrackEmail.php |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +<?php |
| 3 | +class TradeTrackEmail extends QuickTemplate { public function execute() { ?> |
| 4 | + |
| 5 | +<?php |
| 6 | + /** |
| 7 | + * Note that this email does NOT use i18n. The email template is in English. |
| 8 | + * |
| 9 | + * The reason for this is that the people who will be recieving these emails |
| 10 | + * expect them in English, and MediaWiki will happily translate it to French |
| 11 | + * if the user submitting the trademark request is doing so in French. |
| 12 | + * |
| 13 | + * Hence, English here. |
| 14 | + * |
| 15 | + */ |
| 16 | + |
| 17 | +?> |
| 18 | + |
| 19 | + A new request to utilize a Wikimedia trademark has arrived. |
| 20 | + |
| 21 | + Purpose: <?php echo $this->data['tData']['purpose'] ?> |
| 22 | + <?php if ( $this->data['tData']['agreementType'] ) { ?>Agreement Type: <?php echo $this->data['tData']['agreementType'] ?><?php } ?> |
| 23 | + |
| 24 | + Usage: <?php echo $this->data['tData']['usage'] ?> |
| 25 | + |
| 26 | + Marks:<?php foreach ( $this->data['tData']['TRADEMARK_LIST'] as $trademark ) { |
| 27 | + if ( ( isset( $this->data['tData']['trademarks'] ) ) |
| 28 | + && ( in_array( $trademark, $this->data['tData']['trademarks'] ) ) ) { |
| 29 | + echo wfMsg( "tradetrack-which-$trademark" ); |
| 30 | + if ( $trademark == 'other' ) { |
| 31 | + echo $this->data['tData']['otherval']; |
| 32 | + } |
| 33 | + } |
| 34 | + } ?> |
| 35 | + Mailing Address: |
| 36 | + <?php echo $this->data['tData']['mailingaddress'] ?> |
| 37 | + |
| 38 | + Name: <?php echo $this->data['tData']['name'] ?> |
| 39 | + Organization Name: <?php echo $this->data['tData']['orgname'] ?> |
| 40 | + Email: <?php echo $this->data['tData']['email'] ?> |
| 41 | + Phone: <?php echo $this->data['tData']['phone'] ?> |
| 42 | + |
| 43 | +<?php } } |
\ No newline at end of file |
Index: trunk/extensions/TradeTrack/templates/TradeTrackScreenRouting.php |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class TradeTrackScreenRouting extends TradeTrackScreen { public function execute() { ?> |
| 5 | + |
| 6 | +<?php echo wfMsg( 'tradetrack-overview' ) ?> |
| 7 | + |
| 8 | + |
| 9 | +<form method="post" action="<?php echo $this->data['tData']['formURL'] ?>" class="tradetrack-master" id="tradetrack-form"> |
| 10 | + <input type="hidden" name="doaction" value="route" /> |
| 11 | + <div id="tradetrack-screens"> |
| 12 | + |
| 13 | + <p class="tradetrack-f-r"><?php echo wfMsg( 'tradetrack-all-fields-required' ) ?></p> |
| 14 | + <?php if ( $this->data['errors'] ) { ?> |
| 15 | + <div class="tradetrack-errornotice"> |
| 16 | + <?php echo wfMsg( 'tradetrack-errors-have-happened' ) ?> |
| 17 | + <?php $this->showErrors( 'global' ) ?> |
| 18 | + </div> |
| 19 | + <?php } ?> |
| 20 | + <div class="<?php echo ( $this->hasError( 'tradetrack-purpose' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 21 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-purpose-question' ) ?></label><br style="clear:both" /> |
| 22 | + <?php $this->showErrors( 'tradetrack-purpose' ) ?> |
| 23 | + <ul class="tradetrack-element-list"> |
| 24 | + <li><input type="radio" name="tradetrack-purpose" value="Commercial" /> |
| 25 | + <?php echo wfMsg( 'tradetrack-purpose-label-commercial' ) ?> <?php echo wfMsg( 'tradetrack-purpose-expanse-commercial' ) ?></li> |
| 26 | + <li><input type="radio" name="tradetrack-purpose" value="Non-Commercial" /> |
| 27 | + <?php echo wfMsg( 'tradetrack-purpose-label-noncommercial' ) ?> <?php echo wfMsg( 'tradetrack-purpose-expanse-noncommercial' ) ?></li> |
| 28 | + <li><input type="radio" name="tradetrack-purpose" value="Media" /> |
| 29 | + <?php echo wfMsg( 'tradetrack-purpose-label-media' ) ?> <?php echo wfMsg( 'tradetrack-purpose-expanse-media' ) ?></li> |
| 30 | + </ul> |
| 31 | + </div> |
| 32 | + <div class="tradetrack-button-box"> |
| 33 | + <button type="submit" class="tradetrack-button"><?php echo wfMsg( 'tradetrack-button-continue' ) ?></button> |
| 34 | + </div> <!-- buttonbox --> |
| 35 | + </div> <!-- close screens --> |
| 36 | +</form> |
| 37 | + |
| 38 | +<?php } } |
\ No newline at end of file |
Index: trunk/extensions/TradeTrack/templates/TradeTrackScreenThanks.php |
— | — | @@ -0,0 +1,8 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class TradeTrackScreenThanks extends TradeTrackScreen { public function execute() { ?> |
| 5 | + |
| 6 | +<?php echo wfMsg( 'tradetrack-thanks-text' ) ?> |
| 7 | + |
| 8 | + |
| 9 | +<?php } } |
\ No newline at end of file |
Index: trunk/extensions/TradeTrack/templates/TradeTrackScreenDetailsForm.php |
— | — | @@ -0,0 +1,116 @@ |
| 2 | +<?php |
| 3 | +class TradeTrackScreenDetailsForm extends TradeTrackScreen { public function execute() { ?> |
| 4 | + |
| 5 | +<?php echo wfMsg( 'tradetrack-overview' ) ?> |
| 6 | + |
| 7 | +<form method="post" action="<?php echo $this->data['tData']['formURL'] ?>" class="tradetrack-master" id="tradetrack-form"> |
| 8 | + <input type="hidden" name="doaction" value="details" /> |
| 9 | + <input type="hidden" name="tradetrack-purpose" value="<?php echo $this->data['tData']['purpose'] ?>" /> |
| 10 | + <?php if ( $this->data['tData']['agreementType'] ) { ?> |
| 11 | + <input type="hidden" name="tradetrack-elements-agreement" value="<?php echo $this->data['tData']['agreementType'] ?>" /> |
| 12 | + <?php } ?> |
| 13 | + |
| 14 | + <div id="tradetrack-screens"> |
| 15 | + <p class="tradetrack-f-r"><?php echo wfMsg( 'tradetrack-all-fields-required' ) ?></p> |
| 16 | + <?php if ( $this->data['errors'] ) { ?> |
| 17 | + <div class="tradetrack-errornotice"> |
| 18 | + <?php echo wfMsg( 'tradetrack-errors-have-happened' ) ?> |
| 19 | + <?php $this->showErrors( 'global' ) ?> |
| 20 | + </div> |
| 21 | + <?php } ?> |
| 22 | + |
| 23 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-usage' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 24 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-usage-label' ) ?></label> |
| 25 | + <span class="tradetrack-field-hint" |
| 26 | + title="<?php echo wfMsg( 'tradetrack-usage-expanse' ) ?>" |
| 27 | + original-title="<?php echo wfMsg( 'tradetrack-usage-expanse' ) ?>"></span><br style="clear:both" /> |
| 28 | + <?php $this->showErrors( 'tradetrack-elements-usage' ) ?> |
| 29 | + <textarea rows="5" id="tradetrack-elements-usage-textarea" name="tradetrack-elements-usage"><?php echo $this->data['tData']['usage'] ?></textarea><br /> |
| 30 | + <div class="characters-remaining-box"><span id="tradetrack-elements-usage-count"></span> <?php echo wfMsg( 'tradetrack-characters-remaining-notice' ); ?></div> |
| 31 | + </div> |
| 32 | + <div class="<?php echo ( ( ( $this->hasError( 'tradetrack-element-list' ) ) || ( $this->hasError( 'tradetrack-elements-otherval' ) ) ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 33 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-logo-which' ) ?></label><br /> |
| 34 | + <?php $this->showErrors( 'tradetrack-element-list' ) ?> |
| 35 | + <?php $this->showErrors( 'tradetrack-elements-otherval' ) ?> |
| 36 | + <ul class="tradetrack-element-list"> |
| 37 | + <?php foreach ( $this->data['tData']['TRADEMARK_LIST'] as $trademark ) { ?> |
| 38 | + |
| 39 | + <li><input type="checkbox" name="tradetrack-which-<?php echo $trademark ?>" value="true" |
| 40 | + <?php if ( ( isset( $this->data['tData']['trademarks'] ) ) |
| 41 | + && ( in_array( $trademark, $this->data['tData']['trademarks'] ) ) ) { ?> |
| 42 | + checked="checked" |
| 43 | + <?php } ?> |
| 44 | + |
| 45 | + /><?php echo wfMsg( "tradetrack-which-$trademark" ) ?> |
| 46 | + <?php if ( $trademark == 'other' ) { ?> |
| 47 | + <input type="text" name="tradetrack-elements-otherval" maxlength="200" value="<?php echo $this->data['tData']['otherval'] ?>" /> |
| 48 | + <?php } ?> |
| 49 | + </li> |
| 50 | + <?php } ?> |
| 51 | + </ul> |
| 52 | + </div> |
| 53 | + |
| 54 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-mailingaddress' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 55 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-about-label-mailingaddress' ) ?></label> |
| 56 | + <span class="tradetrack-field-hint" |
| 57 | + title="<?php echo wfMsg( 'tradetrack-about-expanse-mailingaddress' ) ?>" |
| 58 | + original-title="<?php echo wfMsg( 'tradetrack-about-expanse-mailingaddress' ) ?>"></span><br style="clear:both" /> |
| 59 | + <?php $this->showErrors( 'tradetrack-elements-mailingaddress' ) ?> |
| 60 | + <textarea rows="5" id="tradetrack-elements-mailingaddress-textarea" name="tradetrack-elements-mailingaddress"><?php echo $this->data['tData']['mailingaddress'] ?></textarea><br /> |
| 61 | + <div class="characters-remaining-box"><span id="tradetrack-elements-mailingaddress-count"></span> <?php echo wfMsg( 'tradetrack-characters-remaining-notice' ); ?></div> |
| 62 | + </div> |
| 63 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-name' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 64 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-about-label-yourname' ) ?></label><br /> |
| 65 | + <?php $this->showErrors( 'tradetrack-elements-name' ) ?> |
| 66 | + <input type="text" name="tradetrack-elements-name" maxlength="200" value="<?php echo $this->data['tData']['name'] ?>" /><br /> |
| 67 | + </div> |
| 68 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-orgname' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 69 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-about-label-orgname' ) ?></label> |
| 70 | + <span class="tradetrack-field-hint" |
| 71 | + title="<?php echo wfMsg( 'tradetrack-about-expanse-orgname' ) ?>" |
| 72 | + original-title="<?php echo wfMsg( 'tradetrack-about-expanse-orgname' ) ?>"></span><br style="clear:both" /> |
| 73 | + <?php $this->showErrors( 'tradetrack-elements-orgname' ) ?> |
| 74 | + <input type="text" name="tradetrack-elements-orgname" maxlength="200" value="<?php echo $this->data['tData']['orgname'] ?>" /><br /> |
| 75 | + </div> |
| 76 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-email' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 77 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-about-label-email' ) ?></label> |
| 78 | + <span class="tradetrack-field-hint" |
| 79 | + title="<?php echo wfMsg( 'tradetrack-about-expanse-email' ) ?>" |
| 80 | + original-title="<?php echo wfMsg( 'tradetrack-about-expanse-email' ) ?>"></span><br style="clear:both" /> |
| 81 | + <?php $this->showErrors( 'tradetrack-elements-email' ) ?> |
| 82 | + <input type="text" name="tradetrack-elements-email" maxlength="200" value="<?php echo $this->data['tData']['email'] ?>" /><br /> |
| 83 | + </div> |
| 84 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-confirmemail' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 85 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-about-label-confirmemail' ) ?></label> |
| 86 | + <span class="tradetrack-field-hint" |
| 87 | + title="<?php echo wfMsg( 'tradetrack-about-expanse-confirmemail' ) ?>" |
| 88 | + original-title="<?php echo wfMsg( 'tradetrack-about-expanse-confirmemail' ) ?>"></span><br style="clear:both" /> |
| 89 | + <?php $this->showErrors( 'tradetrack-elements-confirmemail' ) ?> |
| 90 | + <input type="text" name="tradetrack-elements-confirmemail" maxlength="200" value="<?php echo $this->data['tData']['confirmemail'] ?>" /><br /> |
| 91 | + </div> |
| 92 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-phone' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 93 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-about-label-phone' ) ?></label><br style="clear:both" /> |
| 94 | + <?php $this->showErrors( 'tradetrack-elements-phone' ) ?> |
| 95 | + <input type="text" name="tradetrack-elements-phone" maxlength="200" value="<?php echo $this->data['tData']['phone'] ?>" /><br /> |
| 96 | + </div> |
| 97 | + <div class="<?php echo ( $this->hasError( 'tradetrack-statement-value' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 98 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-statement-label' ) ?></label><br /> |
| 99 | + <span class="tradetrack-question-expanse"><?php echo wfMsg( 'tradetrack-statement-expanse' ) ?></span><br /> |
| 100 | + <?php $this->showErrors( 'tradetrack-statement-value' ) ?> |
| 101 | + <ul class="tradetrack-element-list"> |
| 102 | + <li><input type="checkbox" |
| 103 | + name="tradetrack-elements-statementagreement" |
| 104 | + value="true" |
| 105 | + <?php echo ( $this->data['tData']['statementagreement'] == "true" ) ? 'checked="checked"' : "" ?> |
| 106 | + /> |
| 107 | + <?php echo wfMsg( 'tradetrack-statement-checkboxlabel' ) ?> |
| 108 | + </li> |
| 109 | + </ul> |
| 110 | + </div> |
| 111 | + <div class="tradetrack-button-box"> |
| 112 | + <button type="submit" class="tradetrack-button"><?php echo wfMsg( 'tradetrack-button-submit' ) ?></button> |
| 113 | + </div> <!-- buttonbox --> |
| 114 | + </div> <!-- close screen --> |
| 115 | +</form> |
| 116 | + |
| 117 | +<?php } } |
\ No newline at end of file |
Index: trunk/extensions/TradeTrack/templates/TradeTrackScreen.php |
— | — | @@ -0,0 +1,48 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * This class extends QuickTemplate, adding two things: |
| 6 | + * 1) A constructor that takes a data array as an argument (rather than requiring it to be set later) |
| 7 | + * 2) Adds a method for displaying an array of error strings, given a target field. |
| 8 | + * |
| 9 | + * @author bharris |
| 10 | + */ |
| 11 | +abstract class TradeTrackScreen extends QuickTemplate { |
| 12 | + |
| 13 | + public function __contruct( array $data ) { |
| 14 | + $this->data = $data; |
| 15 | + } |
| 16 | + |
| 17 | + /** |
| 18 | + * This displays a list of error messages for a single field. |
| 19 | + * |
| 20 | + * @param $target The target field for the errors. |
| 21 | + */ |
| 22 | + public function showErrors( $target ) { |
| 23 | + $errors = $this->data['errors']; |
| 24 | + if ( ( isset( $errors ) ) && ( isset( $errors[$target] ) ) ) { |
| 25 | + $eList = $errors[$target]; |
| 26 | + $theHTML = '<ul class="tradetrack-errors">'; |
| 27 | + foreach ( $eList as $e ) { |
| 28 | + $theHTML .= '<li>' . $e . '</li>'; |
| 29 | + } |
| 30 | + $theHTML .= '</ul>'; |
| 31 | + echo $theHTML; |
| 32 | + } |
| 33 | + return; |
| 34 | + } |
| 35 | + /** |
| 36 | + * Tests whether or not a specified target has an error. |
| 37 | + * |
| 38 | + * @param $target The target field |
| 39 | + * @return boolean true or false, depending. |
| 40 | + */ |
| 41 | + public function hasError ( $target ) { |
| 42 | + $errors = $this->data['errors']; |
| 43 | + if ( ( isset( $errors ) ) && ( isset( $errors[$target] ) ) ) { |
| 44 | + return true; |
| 45 | + } |
| 46 | + return false; |
| 47 | + } |
| 48 | + |
| 49 | +} |
\ No newline at end of file |
Index: trunk/extensions/TradeTrack/templates/TradeTrackScreenNonComAgreement.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | +class TradeTrackScreenNonComAgreement extends TradeTrackScreen { public function execute() { ?> |
| 4 | + |
| 5 | +<?php echo wfMsg( 'tradetrack-overview' ) ?> |
| 6 | + |
| 7 | +<form method="post" action="<?php echo $this->data['tData']['formURL'] ?>" class="tradetrack-master" id="tradetrack-form"> |
| 8 | + <input type="hidden" name="doaction" value="noncomroute" /> |
| 9 | + <input type="hidden" name="tradetrack-purpose" value="<?php echo $this->data['tData']['purpose'] ?>" /> |
| 10 | + |
| 11 | + <div id="tradetrack-screens"> |
| 12 | + |
| 13 | + <p class="tradetrack-f-r"><?php echo wfMsg( 'tradetrack-all-fields-required' ) ?></p> |
| 14 | + <?php if ( $this->data['errors'] ) { ?> |
| 15 | + <div class="tradetrack-errornotice"> |
| 16 | + <?php echo wfMsg( 'tradetrack-errors-have-happened' ) ?> |
| 17 | + <?php $this->showErrors( 'global' ) ?> |
| 18 | + </div> |
| 19 | + <?php } ?> |
| 20 | + <div class="<?php echo ( $this->hasError( 'tradetrack-elements-agreement' ) ? 'tradetrack-element-error' : 'tradetrack-element' ) ?>"> |
| 21 | + |
| 22 | + <label class="tradetrack-question-label"><?php echo wfMsg( 'tradetrack-nonprofit-preexisting-agreement-question' ) ?></label> |
| 23 | + <br style="clear:both" /> |
| 24 | + <?php $this->showErrors( 'tradetrack-elements-agreement' ) ?> |
| 25 | + |
| 26 | + <ul class="tradetrack-element-list"> |
| 27 | + <li><input type="radio" name="tradetrack-elements-agreement" value="Yes" /> |
| 28 | + <?php echo wfMsg( 'tradetrack-nonprofit-preexisting-agreement-yes' ) ?></li> |
| 29 | + <li><input type="radio" name="tradetrack-elements-agreement" value="No" /> |
| 30 | + <?php echo wfMsg( 'tradetrack-nonprofit-preexisting-agreement-no-unaffilliated' ) ?></li> |
| 31 | + <li><input type="radio" name="tradetrack-elements-agreement" value="Mistake" /> |
| 32 | + <?php echo wfMsg( 'tradetrack-nonprofit-preexisting-agreement-no-mistake' ) ?></li> |
| 33 | + </ul> |
| 34 | + </div> |
| 35 | + <div class="tradetrack-button-box"> |
| 36 | + <button id="tradetrack-elements-back" class="tradetrack-button"><?php echo wfMsg( 'tradetrack-button-back' ) ?></button> |
| 37 | + <button type="submit" class="tradetrack-button"><?php echo wfMsg( 'tradetrack-button-continue' ) ?></button> |
| 38 | + </div> <!-- buttonbox --> |
| 39 | + </div> <!-- close screens --> |
| 40 | +</form> |
| 41 | + |
| 42 | +<?php } } |
\ No newline at end of file |