zhangxudong 3 ani în urmă
comite
a2144287ae
100 a modificat fișierele cu 10517 adăugiri și 0 ștergeri
  1. 48 0
      genomedb/Dockerfile
  2. BIN
      mydata/files.tar.gz
  3. BIN
      mydata/pgsql.tar.gz
  4. 14 0
      mydata/themes/bootstrap/.gitignore
  5. 339 0
      mydata/themes/bootstrap/LICENSE.txt
  6. 28 0
      mydata/themes/bootstrap/README.md
  7. 190 0
      mydata/themes/bootstrap/bootstrap.api.php
  8. 216 0
      mydata/themes/bootstrap/bootstrap.info
  9. 30 0
      mydata/themes/bootstrap/composer.json
  10. 69 0
      mydata/themes/bootstrap/docs/Contributing.md
  11. 199 0
      mydata/themes/bootstrap/docs/Getting-Started.md
  12. 100 0
      mydata/themes/bootstrap/docs/Maintainers.md
  13. 73 0
      mydata/themes/bootstrap/docs/README.md
  14. 143 0
      mydata/themes/bootstrap/docs/Sub-Theming.md
  15. 91 0
      mydata/themes/bootstrap/docs/Theme-Registry.md
  16. 156 0
      mydata/themes/bootstrap/docs/Theme-Settings.md
  17. BIN
      mydata/themes/bootstrap/favicon.ico
  18. 456 0
      mydata/themes/bootstrap/includes/alter.inc
  19. 661 0
      mydata/themes/bootstrap/includes/cdn.inc
  20. 37 0
      mydata/themes/bootstrap/includes/cdn/Custom.php
  21. 325 0
      mydata/themes/bootstrap/includes/cdn/JsDelivr.php
  22. 375 0
      mydata/themes/bootstrap/includes/cdn/ProviderBase.php
  23. 1557 0
      mydata/themes/bootstrap/includes/common.inc
  24. 104 0
      mydata/themes/bootstrap/includes/deprecated.inc
  25. 40 0
      mydata/themes/bootstrap/includes/icons.inc
  26. 134 0
      mydata/themes/bootstrap/includes/pre-render.inc
  27. 110 0
      mydata/themes/bootstrap/includes/process.inc
  28. 509 0
      mydata/themes/bootstrap/includes/registry.inc
  29. 182 0
      mydata/themes/bootstrap/js/bootstrap.admin.js
  30. 281 0
      mydata/themes/bootstrap/js/bootstrap.js
  31. 86 0
      mydata/themes/bootstrap/js/misc/_collapse.js
  32. 110 0
      mydata/themes/bootstrap/js/misc/_progress.js
  33. 203 0
      mydata/themes/bootstrap/js/misc/_vertical-tabs.js
  34. 88 0
      mydata/themes/bootstrap/js/misc/ajax.js
  35. 252 0
      mydata/themes/bootstrap/js/misc/autocomplete.js
  36. 24 0
      mydata/themes/bootstrap/js/misc/states.js
  37. 15 0
      mydata/themes/bootstrap/js/misc/tabledrag.js
  38. 32 0
      mydata/themes/bootstrap/js/modules/comment/_comment-node-form.js
  39. 150 0
      mydata/themes/bootstrap/js/modules/ctools/js/modal.js
  40. 27 0
      mydata/themes/bootstrap/js/modules/dashboard/dashboard.js
  41. 43 0
      mydata/themes/bootstrap/js/modules/field_ui/field_ui.js
  42. 105 0
      mydata/themes/bootstrap/js/modules/file/file.js
  43. 24 0
      mydata/themes/bootstrap/js/modules/filter/filter.js
  44. 162 0
      mydata/themes/bootstrap/js/modules/user/user.js
  45. 12 0
      mydata/themes/bootstrap/js/modules/views/js/ajax_view.js
  46. BIN
      mydata/themes/bootstrap/logo.png
  47. BIN
      mydata/themes/bootstrap/screenshot.png
  48. 70 0
      mydata/themes/bootstrap/starterkits/THEMENAME/THEMENAME.starterkit
  49. 4 0
      mydata/themes/bootstrap/starterkits/THEMENAME/css/style.css
  50. BIN
      mydata/themes/bootstrap/starterkits/THEMENAME/favicon.ico
  51. BIN
      mydata/themes/bootstrap/starterkits/THEMENAME/logo.png
  52. BIN
      mydata/themes/bootstrap/starterkits/THEMENAME/screenshot.png
  53. 8 0
      mydata/themes/bootstrap/starterkits/THEMENAME/template.php
  54. 4 0
      mydata/themes/bootstrap/starterkits/THEMENAME/templates/README.md
  55. 69 0
      mydata/themes/bootstrap/template.php
  56. 32 0
      mydata/themes/bootstrap/templates/admin_menu/admin-menu-links.vars.php
  57. 69 0
      mydata/themes/bootstrap/templates/block/block-admin-display-form.tpl.php
  58. 59 0
      mydata/themes/bootstrap/templates/block/block.tpl.php
  59. 47 0
      mydata/themes/bootstrap/templates/block/block.vars.php
  60. 54 0
      mydata/themes/bootstrap/templates/book/book-navigation.tpl.php
  61. 65 0
      mydata/themes/bootstrap/templates/book/book-navigation.vars.php
  62. 45 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-carousel.tpl.php
  63. 84 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-carousel.vars.php
  64. 21 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-dropdown.func.php
  65. 128 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-dropdown.vars.php
  66. 33 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-modal.tpl.php
  67. 60 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-modal.vars.php
  68. 29 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-panel.tpl.php
  69. 127 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-panel.vars.php
  70. 27 0
      mydata/themes/bootstrap/templates/bootstrap/bootstrap-search-form-wrapper.func.php
  71. 36 0
      mydata/themes/bootstrap/templates/date/date-views-pager.tpl.php
  72. 108 0
      mydata/themes/bootstrap/templates/date/date-views-pager.vars.php
  73. 69 0
      mydata/themes/bootstrap/templates/file/file-managed-file.func.php
  74. 96 0
      mydata/themes/bootstrap/templates/file/file-upload-help.func.php
  75. 135 0
      mydata/themes/bootstrap/templates/file/file-widget-multiple.func.php
  76. 54 0
      mydata/themes/bootstrap/templates/file/file-widget.func.php
  77. 30 0
      mydata/themes/bootstrap/templates/filter/filter-tips-more-info.func.php
  78. 120 0
      mydata/themes/bootstrap/templates/filter/filter-tips.func.php
  79. 31 0
      mydata/themes/bootstrap/templates/filter/text-format-wrapper.func.php
  80. 29 0
      mydata/themes/bootstrap/templates/icon/icon.vars.php
  81. 43 0
      mydata/themes/bootstrap/templates/image/image-widget.func.php
  82. 101 0
      mydata/themes/bootstrap/templates/menu/menu-link.func.php
  83. 31 0
      mydata/themes/bootstrap/templates/menu/menu-link.vars.php
  84. 59 0
      mydata/themes/bootstrap/templates/menu/menu-local-action.func.php
  85. 42 0
      mydata/themes/bootstrap/templates/menu/menu-local-tasks.func.php
  86. 90 0
      mydata/themes/bootstrap/templates/menu/menu-tree.func.php
  87. 118 0
      mydata/themes/bootstrap/templates/node/node.tpl.php
  88. 25 0
      mydata/themes/bootstrap/templates/picture/image-srcset.vars.php
  89. 22 0
      mydata/themes/bootstrap/templates/picture/picture.vars.php
  90. 25 0
      mydata/themes/bootstrap/templates/poll/poll-bar--block.tpl.php
  91. 25 0
      mydata/themes/bootstrap/templates/poll/poll-bar.tpl.php
  92. 39 0
      mydata/themes/bootstrap/templates/search/search-block-form.tpl.php
  93. 45 0
      mydata/themes/bootstrap/templates/system/breadcrumb.func.php
  94. 47 0
      mydata/themes/bootstrap/templates/system/breadcrumb.vars.php
  95. 49 0
      mydata/themes/bootstrap/templates/system/button.func.php
  96. 50 0
      mydata/themes/bootstrap/templates/system/button.vars.php
  97. 50 0
      mydata/themes/bootstrap/templates/system/container.func.php
  98. 37 0
      mydata/themes/bootstrap/templates/system/date.func.php
  99. 47 0
      mydata/themes/bootstrap/templates/system/exposed-filters.func.php
  100. 29 0
      mydata/themes/bootstrap/templates/system/fieldset.func.php

+ 48 - 0
genomedb/Dockerfile

@@ -0,0 +1,48 @@
+FROM statonlab/tripal3
+MAINTAINER Zhang Xudong <zhangxudong@genek.cn>
+
+USER root
+
+WORKDIR /var/www/html
+
+RUN set -x \
+	# Enable cdetitor and views
+	&& drush dl -y ckeditor \
+	## && drush en -y ckeditor views_ui \
+	# Tripal Daemon
+ 	&& cd /var/www/html/sites/all/libraries \
+	&& wget https://github.com/shaneharter/PHP-Daemon/archive/v2.0.tar.gz \
+	&& tar -zxvf v2.0.tar.gz \
+	&& mv PHP-Daemon-2.0 PHP-Daemon \
+	&& rm v2.0.tar.gz \
+	&& cd /var/www/html \
+	&& drush dl drushd \
+	## && drush en -y drushd tripal_daemon \
+	# Blast
+	&& cd /opt \
+	&& wget https://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/LATEST/ncbi-blast-2.11.0+-x64-linux.tar.gz \
+	&& tar -zxvf ncbi-blast-2.11.0+-x64-linux.tar.gz \
+	&& rm ncbi-blast-2.11.0+-x64-linux.tar.gz \
+	&& cd /var/www/html \
+	&& git clone http://git.genek.cn:3333/zhxd2/tripal_blast.git sites/all/modules/tripal_blast \
+##	&&drush en -y blast_ui \
+	# JBrowse
+	&& yum-config-manager --disable pgdg94 \
+##	&& yum update -y \
+##	&& yum upgrade -y perl \
+	&& yum groupinstall -y "Development Tools" \
+	&& yum install -y zlib-devel perl-ExtUtils-MakeMaker \
+	&& mkdir tools \
+	&& cd tools \
+	&& wget https://github.com/GMOD/jbrowse/releases/download/1.16.11-release/JBrowse-1.16.11.zip \
+	&& unzip JBrowse-1.16.11.zip \
+	&& mv JBrowse-1.16.11 JBrowse \
+	&& cd JBrowse \
+	&& ./setup.sh \
+	&& cd /var/www/html \
+	&& git clone http://git.genek.cn:3333/zhxd2/tripal_jbrowse.git sites/all/modules/tripal_jbrowse
+##	&& drush en -y tripal_jbrowse_mgmt tripal_jbrowse_page \
+
+EXPOSE 80 5432
+
+ENTRYPOINT ["init.sh"]

BIN
mydata/files.tar.gz


BIN
mydata/pgsql.tar.gz


+ 14 - 0
mydata/themes/bootstrap/.gitignore

@@ -0,0 +1,14 @@
+# OS
+.DS_Store
+
+# Applications & Tools
+.idea
+bower_components
+config.codekit
+node_modules
+npm-debug.log
+
+# Project Specific
+.libraries
+lib
+starterkits/*/bootstrap

+ 339 - 0
mydata/themes/bootstrap/LICENSE.txt

@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

+ 28 - 0
mydata/themes/bootstrap/README.md

@@ -0,0 +1,28 @@
+<!-- @file Project Page -->
+# Bootstrap
+
+> Sleek, intuitive, and powerful mobile first front-end framework for faster and
+> easier web development. Bootstrap has become one of the most popular front-end
+> frameworks and open source projects in the world.
+
+This base theme bridges the gap between Drupal and the [Bootstrap Framework].
+
+### Features
+- [jsDelivr CDN](https://www.jsdelivr.com) for "out-of-the-box" styling and
+  faster page load times.
+- [Bootswatch](http://bootswatch.com) theme support, if using the CDN.
+- Glyphicons support via [Icon API](https://www.drupal.org/project/icon).
+- Extensive integration and template/preprocessor overrides for most of the
+  [Bootstrap Framework] CSS, Components and JavaScript
+- Theme settings to further enhance the Drupal Bootstrap integration:
+  - [Breadcrumbs](https://getbootstrap.com/docs/3.4/components/#breadcrumbs)
+  - [Navbar](https://getbootstrap.com/docs/3.4/components/#navbar)
+  - [Popovers](https://getbootstrap.com/docs/3.4/javascript/#popovers)
+  - [Tooltips](https://getbootstrap.com/docs/3.4/javascript/#tooltips)
+  - [Wells](https://getbootstrap.com/docs/3.4/components/#wells) (per region)
+
+### Documentation
+Visit the project's [official documentation site](https://drupal-bootstrap.org)
+or the markdown files inside the `./docs` folder.
+
+[Bootstrap Framework]: https://getbootstrap.com/docs/3.4/

+ 190 - 0
mydata/themes/bootstrap/bootstrap.api.php

@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * @file
+ * List of available hook and alter APIs for use in your sub-theme.
+ */
+
+/**
+ * @defgroup api APIs
+ *
+ * List of available hook and alter APIs for use in your sub-theme.
+ *
+ * @{
+ */
+
+/**
+ * Allows sub-themes to alter the array used for colorizing text.
+ *
+ * @param array $texts
+ *   An associative array containing the text and classes to be matched, passed
+ *   by reference.
+ *
+ * @see _bootstrap_colorize_text()
+ */
+function hook_bootstrap_colorize_text_alter(array &$texts) {
+  // This matches the exact string: "My Unique Button Text".
+  $texts['matches'][t('My Unique Button Text')] = 'primary';
+
+  // This would also match the string above, however the class returned would
+  // also be the one above; "matches" takes precedence over "contains".
+  $texts['contains'][t('Unique')] = 'notice';
+
+  // Remove matching for strings that contain "apply":
+  unset($texts['contains'][t('Apply')]);
+
+  // Change the class that matches "Rebuild" (originally "warning"):
+  $texts['contains'][t('Rebuild')] = 'success';
+}
+
+/**
+ * Allows sub-themes to alter the array used for associating an icon with text.
+ *
+ * @param array $texts
+ *   An associative array containing the text and icons to be matched, passed
+ *   by reference.
+ *
+ * @see _bootstrap_iconize_text()
+ */
+function hook_bootstrap_iconize_text_alter(array &$texts) {
+  // This matches the exact string: "My Unique Button Text".
+  $texts['matches'][t('My Unique Button Text')] = 'heart';
+
+  // This would also match the string above, however the class returned would
+  // also be the one above; "matches" takes precedence over "contains".
+  $texts['contains'][t('Unique')] = 'bullhorn';
+
+  // Remove matching for strings that contain "filter":
+  unset($texts['contains'][t('Filter')]);
+
+  // Change the icon that matches "Upload" (originally "upload"):
+  $texts['contains'][t('Upload')] = 'ok';
+}
+
+/**
+ * This hook allows sub-themes to process all form elements.
+ *
+ * For this hook to be recognized, it must reside directly inside the
+ * template.php file or via a file that is directly included into template.php.
+ *
+ * Any time a hook is added or removed, the Drupal cache must be completely
+ * cleared and rebuilt for the changes to take effect.
+ *
+ * Implementations of this hook should check to see if the element has a
+ * property named #bootstrap_ignore_process and check if it is set to TRUE.
+ * If it is, the hook should immediately return with the unaltered element.
+ *
+ * @param array $element
+ *   The element array, this is NOT passed by reference and must return the
+ *   altered element instead.
+ * @param array $form_state
+ *   The form state array, passed by reference.
+ * @param array $form
+ *   The complete form array, passed by reference.
+ *
+ * @return array
+ *   The altered element array.
+ *
+ * @see bootstrap_element_info_alter()
+ * @see form_builder()
+ * @see drupal_process_form()
+ */
+function hook_form_process(array $element, array &$form_state, array &$form) {
+  return $element;
+}
+
+/**
+ * This hook allows sub-themes to process a specific form element type.
+ *
+ * For this hook to be recognized, it must reside directly inside the
+ * template.php file or via a file that is directly included into template.php.
+ *
+ * Any time a hook is added or removed, the Drupal cache must be completely
+ * cleared and rebuilt for the changes to take effect.
+ *
+ * If there is a matching "form_process_HOOK" function already defined
+ * (provided by core), it will be replaced. The theme replacing it will be
+ * responsible for fully processing the element as it was prior.
+ *
+ * Implementations of this hook should check to see if the element has a
+ * property named #bootstrap_ignore_process and check if it is set to TRUE.
+ * If it is, the hook should immediately return with the unaltered element.
+ *
+ * @param array $element
+ *   The element array, this is NOT passed by reference and must return the
+ *   altered element instead.
+ * @param array $form_state
+ *   The form state array, passed by reference.
+ * @param array $form
+ *   The complete form array, passed by reference.
+ *
+ * @return array
+ *   The altered element array.
+ *
+ * @see bootstrap_element_info_alter()
+ * @see form_builder()
+ * @see drupal_process_form()
+ */
+function hook_form_process_HOOK(array $element, array &$form_state, array &$form) {
+  return $element;
+}
+
+/**
+ * This hook allows sub-themes to alter all elements before it's rendered.
+ *
+ * For this hook to be recognized, it must reside directly inside the
+ * template.php file or via a file that is directly included into template.php.
+ *
+ * Any time a hook is added or removed, the Drupal cache must be completely
+ * cleared and rebuilt for the changes to take effect.
+ *
+ * Implementations of this hook should check to see if the element has a
+ * property named #bootstrap_ignore_pre_render and check if it is set to TRUE.
+ * If it is, the hook should immediately return with the unaltered element.
+ *
+ * @param array $element
+ *   The element array, this is NOT passed by reference and must return the
+ *   altered element instead.
+ *
+ * @return array
+ *   The altered element array.
+ *
+ * @see bootstrap_element_info_alter()
+ */
+function hook_pre_render(array $element) {
+  return $element;
+}
+
+/**
+ * This hook allows sub-themes to alter a specific element before it's rendered.
+ *
+ * For this hook to be recognized, it must reside directly inside the
+ * template.php file or via a file that is directly included into template.php.
+ *
+ * Any time a hook is added or removed, the Drupal cache must be completely
+ * cleared and rebuilt for the changes to take effect.
+ *
+ * If there is a matching "form_pre_render_HOOK" function already defined
+ * (provided by core), it will be replaced. The theme replacing it will be
+ * responsible for fully processing the element as it was prior.
+ *
+ * Implementations of this hook should check to see if the element has a
+ * property named #bootstrap_ignore_pre_render and check if it is set to TRUE.
+ * If it is, the hook should immediately return with the unaltered element.
+ *
+ * @param array $element
+ *   The element array, this is NOT passed by reference and must return the
+ *   altered element instead.
+ *
+ * @return array
+ *   The altered element array.
+ *
+ * @see bootstrap_element_info_alter()
+ */
+function hook_pre_render_HOOK(array $element) {
+  return $element;
+}
+
+/**
+ * @} End of "defgroup subtheme_api".
+ */

+ 216 - 0
mydata/themes/bootstrap/bootstrap.info

@@ -0,0 +1,216 @@
+name = Bootstrap
+description = Built to use Bootstrap, a sleek, intuitive, and powerful front-end framework for faster and easier web development.
+core = 7.x
+php = 5.3.0
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; SimplyTest.me
+;;;;;;;;;;;;;;;;;;;;;
+
+simplytest_dependencies[] = jquery_update
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Regions
+;;;;;;;;;;;;;;;;;;;;;
+
+regions[navigation]     = 'Navigation'
+regions[header]         = 'Top Bar'
+regions[highlighted]    = 'Highlighted'
+regions[help]           = 'Help'
+regions[content]        = 'Content'
+regions[sidebar_first]  = 'Primary'
+regions[sidebar_second] = 'Secondary'
+regions[footer]         = 'Footer'
+regions[page_top]       = 'Page top'
+regions[page_bottom]    = 'Page bottom'
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Theme Settings
+;;;;;;;;;;;;;;;;;;;;;
+
+; Container
+; --------------
+settings[bootstrap_fluid_container] = 0
+
+; Buttons
+; --------------
+settings[bootstrap_button_size] = ''
+settings[bootstrap_button_colorize] = 1
+settings[bootstrap_button_iconize] = 1
+
+; Images
+; --------------
+settings[bootstrap_image_shape] = ''
+settings[bootstrap_image_responsive] = 1
+
+; Tables
+; --------------
+settings[bootstrap_table_bordered] = 0
+settings[bootstrap_table_condensed] = 0
+settings[bootstrap_table_hover] = 1
+settings[bootstrap_table_striped] = 1
+settings[bootstrap_table_responsive] = -1
+
+; Breadcrumbs
+; --------------
+settings[bootstrap_breadcrumb] = 1
+settings[bootstrap_breadcrumb_home] = 0
+settings[bootstrap_breadcrumb_title] = 1
+
+; Navbar
+; --------------
+settings[bootstrap_navbar_position] = ''
+settings[bootstrap_navbar_inverse] = 0
+
+; Pager
+; --------------
+settings[bootstrap_pager_first_and_last] = 1
+
+; Region Wells
+; --------------
+settings[bootstrap_region_well-navigation] = ''
+settings[bootstrap_region_well-header] = ''
+settings[bootstrap_region_well-highlighted] = ''
+settings[bootstrap_region_well-help] = ''
+settings[bootstrap_region_well-content] = ''
+settings[bootstrap_region_well-sidebar_first] = 'well'
+settings[bootstrap_region_well-sidebar_second] = ''
+settings[bootstrap_region_well-footer] = ''
+
+; Anchors
+; --------------
+settings[bootstrap_anchors_fix] = 0
+settings[bootstrap_anchors_smooth_scrolling] = 0
+
+; Forms
+; --------------
+settings[bootstrap_forms_required_has_error] = 0
+settings[bootstrap_forms_has_error_value_toggle] = 1
+settings[bootstrap_forms_smart_descriptions] = 1
+settings[bootstrap_forms_smart_descriptions_limit] = 250
+settings[bootstrap_forms_smart_descriptions_allowed_tags] = 'b, code, em, i, kbd, span, strong'
+
+; Popovers
+; --------------
+settings[bootstrap_popover_enabled] = 1
+settings[bootstrap_popover_animation] = 1
+settings[bootstrap_popover_html] = 0
+settings[bootstrap_popover_placement] = 'right'
+settings[bootstrap_popover_selector] = ''
+settings[bootstrap_popover_trigger]['hover'] = 0
+settings[bootstrap_popover_trigger]['focus'] = 0
+settings[bootstrap_popover_trigger]['click'] = 'click'
+settings[bootstrap_popover_trigger_autoclose] = 1
+settings[bootstrap_popover_title] = ''
+settings[bootstrap_popover_content] = ''
+settings[bootstrap_popover_delay] = 0
+settings[bootstrap_popover_container] = 'body'
+
+; Tooltips
+; --------------
+settings[bootstrap_tooltip_enabled] = 1
+settings[bootstrap_tooltip_animation] = 1
+settings[bootstrap_tooltip_html] = 0
+settings[bootstrap_tooltip_placement] = 'auto left'
+settings[bootstrap_tooltip_selector] = ''
+settings[bootstrap_tooltip_trigger]['hover'] = 'hover'
+settings[bootstrap_tooltip_trigger]['focus'] = 'focus'
+settings[bootstrap_tooltip_trigger]['click'] = 0
+settings[bootstrap_tooltip_delay] = 0
+settings[bootstrap_tooltip_container] = 'body'
+
+; Advanced
+; --------------
+settings[bootstrap_cdn_provider] = 'jsdelivr'
+settings[bootstrap_cdn_custom_css] = 'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.css'
+settings[bootstrap_cdn_custom_css_min] = 'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css'
+settings[bootstrap_cdn_custom_js] = 'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.js'
+settings[bootstrap_cdn_custom_js_min] = 'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js'
+settings[bootstrap_cdn_jsdelivr_version] = '3.4.1'
+settings[bootstrap_cdn_jsdelivr_theme] = 'bootstrap'
+
+; Global
+; --------------
+settings[toggle_name] = 1
+settings[toggle_search] = 1
+
+; jQuery Update
+; --------------
+settings[jquery_update_jquery_version] = 2.1
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Excludes
+;;;;;;;;;;;;;;;;;;;;;
+
+; JavaScript
+; --------------
+; exclude[js][] = 'modules/contextual/contextual.js'
+
+; CSS
+; --------------
+; Necessary module CSS.
+
+;exclude[css][] = 'modules/block/block.css'
+;exclude[css][] = 'modules/node/node.css'
+;exclude[css][] = 'modules/system/admin.css'
+;exclude[css][] = 'modules/system/system.css'
+;exclude[css][] = 'modules/system/system.admin.css'
+;exclude[css][] = 'modules/system/system.base.css'
+
+exclude[css][] = 'misc/vertical-tabs.css'
+exclude[css][] = 'modules/aggregator/aggregator.css'
+exclude[css][] = 'modules/book/book.css'
+exclude[css][] = 'modules/comment/comment.css'
+exclude[css][] = 'modules/dblog/dblog.css'
+exclude[css][] = 'modules/file/file.css'
+exclude[css][] = 'modules/filter/filter.css'
+exclude[css][] = 'modules/forum/forum.css'
+exclude[css][] = 'modules/help/help.css'
+exclude[css][] = 'modules/menu/menu.css'
+exclude[css][] = 'modules/openid/openid.css'
+exclude[css][] = 'modules/poll/poll.css'
+exclude[css][] = 'modules/search/search.css'
+exclude[css][] = 'modules/statistics/statistics.css'
+exclude[css][] = 'modules/syslog/syslog.css'
+exclude[css][] = 'modules/system/maintenance.css'
+exclude[css][] = 'modules/system/system.maintenance.css'
+exclude[css][] = 'modules/system/system.menus.css'
+exclude[css][] = 'modules/system/system.messages.css'
+exclude[css][] = 'modules/system/system.theme.css'
+exclude[css][] = 'modules/taxonomy/taxonomy.css'
+exclude[css][] = 'modules/tracker/tracker.css'
+exclude[css][] = 'modules/update/update.css'
+exclude[css][] = 'modules/user/user.css'
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Breakpoints
+;;;;;;;;;;;;;;;;;;;;;
+breakpoints[screen-xs-max] = (max-width: 767px)
+breakpoints[screen-sm-min] = (min-width: 768px)
+breakpoints[screen-sm-max] = (max-width: 991px)
+breakpoints[screen-md-min] = (min-width: 992px)
+breakpoints[screen-md-max] = (max-width: 1199px)
+breakpoints[screen-lg-min] = (min-width: 1200px)
+; Multipiers
+multipliers[screen-xs-max][] = 1.5x
+multipliers[screen-xs-max][] = 2x
+multipliers[screen-sm-min][] = 1.5x
+multipliers[screen-sm-min][] = 2x
+multipliers[screen-sm-max][] = 1.5x
+multipliers[screen-sm-max][] = 2x
+multipliers[screen-md-min][] = 1.5x
+multipliers[screen-md-min][] = 2x
+multipliers[screen-md-max][] = 1.5x
+multipliers[screen-md-max][] = 2x
+multipliers[screen-lg-min][] = 1.5x
+multipliers[screen-lg-min][] = 2x
+
+; Information added by Drupal.org packaging script on 2019-06-20
+version = "7.x-3.26"
+core = "7.x"
+project = "bootstrap"
+datestamp = "1561051701"

+ 30 - 0
mydata/themes/bootstrap/composer.json

@@ -0,0 +1,30 @@
+{
+  "name": "drupal/bootstrap",
+  "description": "Built to use Bootstrap, a sleek, intuitive, and powerful front-end framework for faster and easier web development.",
+  "type": "drupal-theme",
+  "license": "GPL-2.0",
+  "homepage": "https://www.drupal.org/project/bootstrap",
+  "authors": [
+    {
+      "name": "Mark Carver (markcarver)",
+      "homepage": "https://www.drupal.org/u/markcarver",
+      "role": "Maintainer"
+    },
+    {
+      "name": "John McCormick (neardark)",
+      "homepage": "https://www.drupal.org/u/neardark",
+      "role": "Co-maintainer"
+    },
+    {
+      "name": "Fabiano Sant'Ana (wundo)",
+      "homepage": "https://www.drupal.org/u/wundo",
+      "role": "Co-maintainer"
+    }
+  ],
+  "support": {
+    "docs": "https://drupal-bootstrap.org",
+    "issues": "https://www.drupal.org/project/issues/bootstrap",
+    "irc": "irc://irc.freenode.org/drupal-bootstrap",
+    "source": "http://cgit.drupalcode.org/bootstrap"
+  }
+}

+ 69 - 0
mydata/themes/bootstrap/docs/Contributing.md

@@ -0,0 +1,69 @@
+<!-- @file Overview on how to contribute to the Drupal Bootstrap project. -->
+<!-- @defgroup -->
+# Contributing
+
+Please read the [Getting Started](<!-- @url getting_started -->) topic and the
+other various topics on this site first before creating an issue in this
+project's issue queue.
+
+Anything that falls within the scope of existing documentation or answered
+questions will be marked as "Closed (works as designed)" or
+"Closed (won't fix)".
+
+The [Theme development](https://www.drupal.org/forum/3) support forum and
+[Drupal StackExchange](https://drupal.stackexchange.com) are also amazing
+resources for asking questions, learning new techniques and overall general
+support.
+
+## Drupal.org Handbook Pages
+There has been some amazing Drupal Community work done around integration
+between Drupal and the [Bootstrap Framework]. Additional community driven
+documentation can be found on the [original Drupal.org handbook pages](https://www.drupal.org/node/1976938).
+
+If you find that the documentation in these locations are inaccurate or
+missing, please update it yourself (all logged in users have edit
+capability).
+
+## Creating New Issues
+
+{.alert.alert-info} **Recommended reading:** [How To Solve All Your [Drupal] Problems](http://www.lullabot.com/blog/article/how-solve-all-your-problems)
+
+{.alert.alert-warning} Please, [search the issue queue](https://www.drupal.org/project/issues/search/bootstrap)
+first. **DO NOT** duplicate existing issues.
+
+**If you find an existing issue and the issue status is:**
+- Closed (fixed, duplicate, won't fix) - **DO NOT** re-open it. Open a new
+  issue (unless it's "Closed (won't fix)") and reference the existing issue in
+  the "Related Issues" field.
+- Active, NR, NW, RTBC - Please update the issue accordingly, **DO NOT** create
+  a new issue.
+
+**The [Drupal Bootstrap] issue queue IS for:**
+- Fixing bugs and adding new features pertaining to the integration between
+  Drupal and the [Bootstrap Framework].
+
+**The [Drupal Bootstrap] issue queue IS NOT for:**
+- Bugs/feature requests pertaining to the [Bootstrap Framework] itself. Use
+  [their issue queue](https://github.com/twbs/bootstrap/issues) instead.
+- Custom CSS/Layout (e.g. site specific)
+- LESS/SASS - Compilation errors, syntax, mixins/functions
+- JavaScript, jQuery, Bootstrap plugins or custom (site specific) plugins
+- Modules that don't work in multiple themes. File the issue with that module.
+  It is likely they are not using [APIs](https://api.drupal.org) properly, not
+  following existing [Coding Standards](https://www.drupal.org/coding-standards)
+  or not developing with [Best Practices](https://www.drupal.org/best-practices) in
+  mind. It is actually a rare event when it is a legitimate issue with the
+  [Drupal Bootstrap] project.
+
+## Slack
+
+The [Drupal Bootstrap] project and its maintainers use the `#bootstrap` channel
+in the `drupal.slack.com` workspace to communicate in real time. Please read
+the following for more information on how to the community uses this technology:
+[Chat with the Drupal community using Slack](https://www.drupal.org/slack).
+
+Please keep in mind though, this **IS NOT** a "support" channel. It's primary
+use is to discuss issues and to help fix bugs with the base theme itself.
+
+[Drupal Bootstrap]: https://www.drupal.org/project/bootstrap
+[Bootstrap Framework]: https://getbootstrap.com/docs/3.4/

+ 199 - 0
mydata/themes/bootstrap/docs/Getting-Started.md

@@ -0,0 +1,199 @@
+<!-- @file The "Getting Started" topic. -->
+<!-- @defgroup -->
+# Getting Started
+
+## Installation
+- Install the Bootstrap base theme in `sites/all/themes` or a similar
+  `sites/*/themes` folder.
+- Enable the [Drupal Bootstrap] base theme. If you do not intend to use the base
+  theme as the default theme, and instead choose to create a sub-theme, you will
+  still need to enable the [Drupal Bootstrap] base theme (see warning below).
+- Ensure your site's jQuery version has been configured to meet the
+  [Bootstrap Framework] minimum version requirement. The preferred method for
+  updating Drupal's jQuery is to install the [jQuery Update] module.
+
+{.alert.alert-warning} **WARNING:** Due to a bug in Drupal 7, base themes may
+appear to still "work" even if they are not enabled. This fact does not mean
+that the base theme still isn't required to be enabled. Not all features will
+work properly if the base theme is disabled, especially if certain
+functionality relies on a list of "enabled" themes.
+
+## Bootstrap Framework Fundamentals
+Generally speaking, you should really read the entire [Bootstrap Framework]
+documentation site, if you haven't already. Here are the four basic "sections"
+that site is split into:
+
+- [Getting Started](https://getbootstrap.com/docs/3.4/getting-started) - An overview of
+  the [Bootstrap Framework], how to download and use, basic templates and
+  examples, and more.
+- [CSS](https://getbootstrap.com/docs/3.4/css/) - Global CSS settings, fundamental HTML
+  elements styled and enhanced with extensible classes, and an advanced grid
+  system.
+- [Components](https://getbootstrap.com/docs/3.4/components/) - Over a dozen reusable
+  components built to provide iconography, dropdowns, input groups, navigation,
+  alerts, and much more.
+- [JavaScript](https://getbootstrap.com/docs/3.4/javascript/) - Bring the
+  [Bootstrap Framework] components to life with over a dozen custom jQuery
+  plugins. Easily include them all, or one by one.
+  
+## FAQ - Frequently Asked Questions
+
+- [Do you support X module?](#support)
+- [Do you support Internet Explorer?](#ie)
+- [Is Drupal Bootstrap a module or theme?](#module-or-theme)
+- [What does the JavaScript error `TypeError: $(...).on is not a function`
+  mean?](#jquery)
+- [Where can I discuss an issue in real time?](#discuss)
+- [Where should I make changes?](#changes)
+- [Why are my sub-theme's `.info` settings ignored?](#theme-settings-ignored)
+
+---
+
+### Q: Do you support X module? {#support}
+**A: Possibly**
+
+Below are a list of modules the [Drupal Bootstrap] base theme actively supports.
+This list is constantly growing and each module's support has usually been
+implemented because of either extremely high usage or the fact it was designed
+explicitly for use with this base theme and has maintainers in both projects.
+
+**Supported modules:**
+- [Admin Menu](https://www.drupal.org/project/admin_menu)
+- [Bootstrap Core](https://www.drupal.org/project/bootstrap_core)
+- [Disable Messages](https://www.drupal.org/project/disable_messages)
+- [jQuery Update](https://www.drupal.org/project/jquery_update)
+- [Icon API](https://www.drupal.org/project/icon)
+- [Path Breadcrumbs](https://www.drupal.org/project/path_breadcrumbs)
+- [Picture](https://www.drupal.org/project/picture)
+- [Views](https://www.drupal.org/project/picture) _(partial support)_
+- [Webform](https://www.drupal.org/project/webform) _(partial support)_
+
+The following modules are "un-supported modules" and are not documented by the
+[Drupal Bootstrap] base theme. This does not mean that the base theme will not
+work with them or that they are "bad". It simply means that this project does
+not have the time, energy or effort it would take to document "every possible
+scenario".
+
+It is certainly possible that some of these modules may eventually become
+"officially" supported. That will happen only, of course, if there are enough
+people to help contribute solid solutions and make supporting them by the base
+theme maintainers a relatively "easy" task.
+
+Some of these modules may have blogs or videos floating around on the internet.
+However, if you choose to use one of these modules, you are really doing so
+at your own expense. Do not expect support from this base theme or the project
+you are attempting to integrate the base theme with.
+
+**"Un-supported" modules:**
+- Color module (in core)
+- [Bootstrap API](https://www.drupal.org/project/bootstrap_api)
+- [Bootstrap Library](https://www.drupal.org/project/bootstrap_library)
+- [Display Suite](https://www.drupal.org/project/ds)
+- [Display Suite Bootstrap Layouts](https://www.drupal.org/project/ds_bootstrap_layouts)
+- [LESS module](https://www.drupal.org/project/less)
+- [Panels](https://www.drupal.org/project/panels)
+- [Panels Bootstrap Layouts](https://www.drupal.org/project/panels_bootstrap_layouts)
+
+---
+
+### Q: Do you support Internet Explorer? {#ie}
+**A: No, not "officially"**
+
+The [Bootstrap Framework] itself does not officially support older Internet
+Explorer [compatibility modes](https://getbootstrap.com/docs/3.4/getting-started/#support-ie-compatibility-modes).
+To ensure you are using the latest rendering mode for IE, consider installing
+the [HTML5 Tools](https://www.drupal.org/project/html5_tools) module.
+
+Internet Explorer 8 requires the use of [Respond.js] to enable media queries
+(Responsive Web Design). However, [Respond.js] does not work with CSS that is
+referenced via a CSS `@import` statement, which is the default way Drupal
+adds CSS files to a page when CSS aggregation is disabled. To ensure
+[Respond.js] works properly, enable CSS aggregation at the bottom of:
+`admin/config/development/performance`.
+
+---
+
+### Q: Is Drupal Bootstrap a module or theme? {#module-or-theme}
+**A: Theme**
+
+More specifically a base theme. It is _not_ a module. Modules are allowed to
+participate in certain hooks, while themes cannot. This is a very important
+concept to understand and limits themes from participating in a wider range of
+functionality.
+
+---
+
+### Q: What does the JavaScript error `TypeError: $(...).on is not a function` mean? {#jquery}
+Drupal 7 ships with the `1.4.4` version of jQuery out-of-the-box. The [$.on()](http://api.jquery.com/on/)
+method was introduced several versions after this in jQuery version `1.7`.
+
+You must upgrade your site or sub-theme's jQuery Version by installing (and
+properly configuring) the [jQuery Update] module to use a jQuery version
+compatible with the [Bootstrap Framework]. This is typically a version greater
+than or equal to `1.9`.
+
+Ensuring jQuery compatibilities between Drupal, the [Bootstrap Framework] and
+other plugins/modules does not fall within the scope of this base theme's
+documentation or support.
+
+---
+
+### Q: Where can I discuss an issue in real time? {#discuss}
+**A: In Slack**
+
+The [Drupal Bootstrap] project and its maintainers use the `#bootstrap` channel
+in the `drupal.slack.com` workspace to communicate in real time. Please read
+the following for more information on how to the community uses this technology:
+[Chat with the Drupal community using Slack](https://www.drupal.org/slack).
+
+Please keep in mind though, this **IS NOT** a "support" channel. It's primary
+use is to discuss issues and to help fix bugs with the base theme itself.
+
+---
+
+### Q: Where should I make changes? {#changes}
+**A: In a custom sub-theme**
+
+You should **never** modify any theme or sub-theme that is packaged and released
+from Drupal.org. If you do, all changes you have made would be lost once that
+theme is updated. This makes keeping track of changes next to impossible.
+
+Instead, you should create a custom sub-theme that isn't hosted on Drupal.org.
+
+---
+
+### Q: Why are my sub-theme's `.info` settings ignored? {#theme-settings-ignored}
+**A: The database contains a copy of the theme settings and they take
+precedence over theme settings stored in the `.info` file.**
+
+This is actually quite a common issue whenever a theme's settings are saved
+from the UI. This action stores the settings in the {variables} table of the
+database. The workflow for theme_get_setting() merges the settings from the
+database on top of the settings found in the theme's `.info` file.
+
+You need to remove the variable `theme_[theme_name]_settings` from the database,
+where `[theme_name]` is your sub-theme's machine name (e.g. if your sub-theme
+machine name is `THEME_NAME`, the variable name would be
+`theme_THEME_NAME_settings`).
+
+The easiest way to do accomplish this task is to use the following [Drush]
+command: `theme_THEME_NAME_settings`
+
+If you do not have or use [Drush], you will either have to manually delete this
+variable from the database or create an [update hook](https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_update_N/7)
+in a custom module that deletes the variable for you:
+
+```php
+/**
+* Remove the 'theme_THEME_NAME_settings' variable.
+*/
+function hook_update_N() {
+  variable_del('theme_THEME_NAME_settings');
+}
+```
+
+[Drush]: http://www.drush.org
+[Drupal Bootstrap]: https://www.drupal.org/project/bootstrap
+[Bootstrap Framework]: https://getbootstrap.com/docs/3.4/
+[jQuery Update]: https://www.drupal.org/project/jquery_update
+[Respond.js]: https://github.com/scottjehl/Respond

+ 100 - 0
mydata/themes/bootstrap/docs/Maintainers.md

@@ -0,0 +1,100 @@
+<!-- @file Maintaining the Drupal Bootstrap project. -->
+<!-- @defgroup -->
+# Maintainers
+
+Generally speaking, these topics will not be very helpful to you unless you are
+a maintainer for this project. If you're simply curious about the process or
+even want to help improve this aspect of the project, all suggestions will be
+appreciated!
+
+## Drupal Bootstrap Styles
+The stylesheets bundled with this base theme (formerly known as "overrides")
+have moved to a separate and dedicated project. Please file issues there:
+
+https://github.com/unicorn-fail/drupal-bootstrap-styles
+
+## Releases
+This project attempts to provide more structured release notes. This allows the
+project to communicate more effectively to the users what exactly has changed
+and where to go for additional information. This documentation is intended for
+the project maintainers to help provide consistent results between releases.
+
+### Release notes template
+The following is just a template to show a typical structured format used as
+release notes for this project:
+
+```html
+<h3 id="change-records">Change Records</h3>
+<!-- Change records table HTML -->
+
+Optionally, you can insert any additional verbiage here.
+However, if it is long, it should really be a change record.
+
+<p>&nbsp;</p>
+<h3 id="notes">Notes</h3>
+
+<p>&nbsp;</p>
+<p>Changes since <!-- previous release --> (<!-- commit count -->):</p>
+
+<h3 id="security">Security Announcements</h3>
+<ul>
+  <li><!-- Issue/Commit Message --></li>
+</ul>
+
+<h3 id="features">New Features</h3>
+<ul>
+  <li><!-- Issue/Commit Message --></li>
+</ul>
+
+<h3 id="bugs">Bug Fixes</h3>
+<ul>
+  <li><!-- Issue/Commit Message --></li>
+</ul>
+```
+
+### Create a Release Node
+
+{.alert.alert-info} **NOTE:** This project currently relies on the
+[Drush Git Release Notes](https://www.drupal.org/project/grn) tool to
+automatically generate the the bulk of the release notes. This does, however,
+requires maintainers to do the following extra steps. This entire process will
+eventually be converted into a fully automated grunt task. Until then, please
+download and install this tool and follow the remaining steps.
+
+1. Create a [tag in git](https://www.drupal.org/node/1066342) that follows the
+   previous version and push it to the repository.
+2. Create a [project release node](https://www.drupal.org/node/1068944) for this
+   newly created tag.
+3. _(Skip this step if this is a new "alpha/beta" release)_ In a separate tab,
+   go to this project's [releases](https://www.drupal.org/node/259843/release)
+   page. Open and edit the previous release node. It should have followed the
+   release note template. If it has, copy and paste its contents into the new
+   release node body.
+4. In a separate tab, go to the [change records](https://www.drupal.org/list-changes/bootstrap)
+   for this project and filter by the new official release version
+   ("alpha/beta/RC" releases should always use the next "official" version for
+   their change records). If there are no change records, then remove this
+   section. Otherwise, copy and paste the entire table into the template
+   (replacing any existing one, if necessary).
+5. Generate a list of issues/commits by executing the following from the root
+   of the project:
+
+   `drush release-notes <old> <new> --commit-count`
+   (e.g. `drush release-notes 7.x-3.0 7.x-3.1 --commit-count`)
+
+   If this is a follow-up "alpha/beta/RC" release, always use the last
+   "alpha/beta/RC" release version instead. This will allow for a quicker
+   parsing of the list to merge into the previously copied release notes:
+
+   `drush release-notes <old> <new> --commit-count`
+   (e.g. `drush release-notes 7.x-3.1-beta2 7.x-3.1-beta3 --commit-count`)
+
+6. Copy the entire generated output into the template, just under where the
+   "Change Records" section would be, replacing only the commit count (do not
+   replace the "since last {offical} version").
+7. Go though each item (`<li>`) that contains an issue link, ignoring duplicates
+   and standalone verbiage (direct commits). Move (cut and paste) these items
+   into the appropriate "New Features" or "Bug Fixes" sections.
+8. Once complete the generated list should be empty (e.g. `<ul></ul>`), remove
+   it.
+9. Save the release node.

+ 73 - 0
mydata/themes/bootstrap/docs/README.md

@@ -0,0 +1,73 @@
+<!-- @file Documentation landing page and topics for the https://drupal-bootstrap.org site. -->
+<!-- @mainpage -->
+# Drupal Bootstrap Documentation
+
+{.lead} The official documentation site for the [Drupal Bootstrap] base theme
+
+The majority of this site is automatically generated from source files
+located through out the project's repository. Topics are extracted from Markdown
+files and the rest is extracted from embedded PHP comments.
+
+---
+
+## Topics
+
+Below are some topics to help get you started using the [Drupal Bootstrap] base
+theme. They are ordered based on the level one typically progresses while using
+a base theme like this.
+
+#### [Contributing](<!-- @url contributing -->)
+
+#### [Getting Started](<!-- @url getting_started -->)
+
+#### [Theme Settings](<!-- @url theme_settings -->)
+
+#### [Sub-Theming](<!-- @url sub_theming -->)
+
+#### [Utilities](<!-- @url utility -->)
+
+#### [Theme Registry](<!-- @url registry -->)
+
+- [Preprocess Functions (.vars.php)](<!-- @url theme_preprocess -->)
+- [Process Functions (.vars.php)](<!-- @url theme_process -->)
+- [Templates (.tpl.php)](<!-- @url templates -->)
+- [Theme Functions (.func.php)](<!-- @url theme_functions -->)
+
+#### [Project Maintainers](<!-- @url maintainers -->)
+
+---
+
+## Terminology
+
+The term **"bootstrap"** can be used excessively through out this project's
+documentation. For clarity, we will always attempt to use this word verbosely
+in one of the following ways:
+
+- **[Drupal Bootstrap]** refers to the Drupal base theme project.
+- **[Bootstrap Framework]** refers to the external front end framework.
+- **[`drupal_bootstrap`](https://api.drupal.org/apis/drupal_bootstrap)** refers
+  to Drupal's bootstrapping process or phase.
+  
+When referring to files inside the [Drupal Bootstrap] project directory, they
+will always start with `./sites/all/themes/bootstrap` and continue to specify
+the full path to the file or directory inside it. The dot (`.`) is
+representative of your Drupal installation's `DOCROOT` folder. For example, the
+file that is responsible for displaying the text on this page is located at
+`./sites/all/themes/bootstrap/docs/README.md`.
+
+When referring to files inside a sub-theme, they will always start with
+`./sites/all/themes/THEMENAME/`, where `THEMENAME` is the machine name of your
+sub-theme. They will continue to specify the full path to the file or directory
+inside it. For example, the primary file Drupal uses to determine if a theme
+exists is: `./sites/all/themes/THEMENAME/THEMENAME.info`.
+
+{.alert.alert-info} **NOTE:** It is common practice to place projects found on
+Drupal.org inside a sub-folder named `contrib` and custom/site-specific code
+inside a `custom` folder. If your site is set up this way, please adjust all
+paths accordingly (i.e. `./sites/all/themes/contrib/bootstrap` and
+`./sites/all/themes/custom/THEMENAME`). If you have a multi-site setup, you
+will need to replace the `all` portion of the path with the appropriate site
+name (i.e. `./sites/example.com/themes/contrib/bootstrap`).
+
+[Drupal Bootstrap]: https://www.drupal.org/project/bootstrap
+[Bootstrap Framework]: https://getbootstrap.com/docs/3.4/

+ 143 - 0
mydata/themes/bootstrap/docs/Sub-Theming.md

@@ -0,0 +1,143 @@
+<!-- @file Instructions on how to sub-theme the Drupal Bootstrap base theme. -->
+<!-- @defgroup sub_theming -->
+# Sub-Theming
+
+If you haven't already installed the Drupal Bootstrap theme, read the
+[Getting Started](<!-- @url getting_started -->) topic. Below are instructions
+on how to create a [Drupal Bootstrap] based sub-theme. There are several
+different variations on how to accomplish this task, but this topic will focus
+on the two primarily and most common ways.
+
+You should never modify any theme or sub-theme that is packaged and released
+from Drupal.org, such as Drupal Bootstrap. If you do, all changes you have made
+will be lost once that theme is updated. Instead, you should create a sub-theme
+from one of the provided starterkits (this is considered a best practice). Once
+you've done that, you can override CSS, templates, and theme processing.
+
+- [Using the Starterkit](#starterkit)
+- [Using Source Files](#source)
+  - [LESS](#less)
+  - [SASS](#sass)
+  - [Compile](#compile)
+- [Override Settings](#settings)
+- [Override Templates](#templates)
+
+## Using the Starterkit {#starterkit}
+
+The starterkit provided by this base-theme supplies the basic file structure on
+how to construct a proper Bootstrap based sub-theme for use with a CDN Provider
+(like [jsDelivr]) or for use with compiling [Bootstrap Framework] source files.
+
+{.alert.alert-info} **NOTE:** Using a CDN Provider is the preferred method
+for loading the [Bootstrap Framework] CSS and JS on simpler sites that do not
+use a site-wide CDN. There are advantages and disadvantages to using a
+CDN Provider and you will need to weigh the benefits based on your site's own
+requirements. Using a CDN Provider does mean that it depends on a third-party
+service. There is no obligation or commitment made by this project or these
+third-party services that guarantees up-time or quality of service. If you need
+to customize Bootstrap, you must compile the [Bootstrap Framework] source code
+locally and disable the
+[`bootstrap_cdn_provider` theme setting](<!-- @url theme_settings -->).
+
+{.alert.alert-warning} **WARNING:** All locally compiled versions of Bootstrap
+will be superseded by any enabled CDN Provider; **do not use both**.
+
+1. Copy `./sites/all/themes/bootstrap/starterkits/THEMENAME` to `./sites/all/themes`.
+   * Rename the `THEMENAME` directory to a unique machine readable name. This is
+   your sub-theme's "machine name". When referring to files inside a sub-theme,
+   they will always start with `./sites/all/themes/THEMENAME/`, where `THEMENAME`
+   is the machine name of your sub-theme. They will continue to specify the full
+   path to the file or directory inside it. For example, the primary file Drupal
+   uses to determine if a theme exists is:
+   `./sites/all/themes/THEMENAME/THEMENAME.info`.
+2. Rename `./sites/all/themes/THEMENAME/THEMENAME.starterkit` to match
+   `./sites/all/themes/THEMENAME/THEMENAME.info`.
+   * Open this file and change the name, description and any other properties
+     to suite your needs.
+   * (Optional) If you plan on using a local precompiler (i.e. [Less] or [Sass])
+     then uncomment the appropriate JavaScript entries inside this file to
+     enable the assets provided by the [Bootstrap Framework].
+   * (Optional) If you plan on using a local precompiler (i.e. [Less] or [Sass])
+     then you will need to disable the
+     [`bootstrap_cdn_provider` theme setting](<!-- @url theme_settings -->).
+     You can do this several different ways, but it's recommended that you
+     uncomment the following line in this file so the CDN Provider is
+     automatically disabled when your sub-theme is installed:
+     ```
+     ; Uncomment if using Sass or Less source files. This disables the CDN provider
+     ; so compiled source files can be used instead.
+     settings[bootstrap_cdn_provider] = ''
+     ```
+
+{.alert.alert-warning} **WARNING:** Ensure that the `.starterkit` suffix is
+not present on your sub-theme's `.info` filename. This suffix is simply a
+stop gap measure to ensure that the bundled starter kit sub-theme cannot be
+enabled or used directly. This helps people unfamiliar with Drupal avoid
+modifying the starter kit sub-theme directly and instead forces them to create
+a new sub-theme to modify.
+
+## Using Source Files {#source}
+
+By default, the starterkit is designed to be used with a CDN Provider for
+quick setup.
+
+While there are a multitude of different approaches on how to actually compile
+the [Bootstrap Framework] source files, this base-theme does not and will not
+provide templates or suggest specific tools to use. It is up to you, the
+developer, to figure out which solution is best for your particular needs.
+
+### LESS {#less}
+- You must understand the basic concept of using the [Less] CSS pre-processor.
+- You must use a **[local Less compiler](https://www.google.com/search?q=less+compiler)**.
+- You must use the latest `3.x.x` version of [Bootstrap Framework LESS Source Files]
+  ending in the `.less` extension, not files ending in `.css`.
+- You must download a copy of [Drupal Bootstrap Styles] and copy over the `less`
+  folder located at `./drupal-bootstrap-styles/src/3.x.x/7.x-3.x/less`.
+
+### SASS {#sass}
+- You must understand the basic concept of using the [Sass] CSS pre-processor.
+- You must use a **[local Sass compiler](https://www.google.com/search?q=sass+compiler)**.
+- You must use the latest `3.x.x` version of [Bootstrap Framework SASS Source Files]
+  ending in the `.scss` extension, not files ending in `.css`.
+- You must download a copy of [Drupal Bootstrap Styles] and copy over the `scss`
+  folder located at `./drupal-bootstrap-styles/src/3.x.x/7.x-3.x/scss`.
+
+### Compile {#compile}
+
+Download and extract the source files into the root of your new sub-theme:
+`./sites/all/themes/THEMENAME`. After it has been extracted, the directory should be
+renamed (if needed) so it reads `./sites/all/themes/THEMENAME/bootstrap`.
+
+If for whatever reason you have an additional `bootstrap` directory wrapping
+the first `bootstrap` directory (e.g. `./sites/all/themes/THEMENAME/bootstrap/bootstrap`),
+remove the wrapping `bootstrap` directory. You will only ever need to touch
+these files if or when you upgrade your version of the [Bootstrap Framework].
+
+{.alert.alert-warning} **WARNING:** Do not modify the files inside of
+`./sites/all/themes/THEMENAME/bootstrap` directly. Doing so may cause issues when
+upgrading the [Bootstrap Framework] in the future.
+
+Depending on which precompiler you chose, you should have a `less/style.less`
+or `scss/style.scss` file respectively. This file is the main compiling entry
+point. Follow further instructions provided by the `README.md` inside the
+`less` or `scss` folder.
+
+## Override Settings {#settings}
+Please refer to the [Theme Settings](<!-- @url theme_settings -->) topic.
+
+## Override Templates {#templates}
+Please refer to the [Templates](<!-- @url templates -->) and
+[Theme Registry](<!-- @url registry -->) topics.
+
+## Enable Your New Sub-theme {#enable}
+In your Drupal site, navigate to `admin/appearance` and click the `Enable and
+set default` link next to your newly created sub-theme.
+
+[Drupal Bootstrap]: https://www.drupal.org/project/bootstrap
+[Drupal Bootstrap Styles]: https://github.com/unicorn-fail/drupal-bootstrap-styles
+[Bootstrap Framework]: https://getbootstrap.com/docs/3.4/
+[Bootstrap Framework LESS Source Files]: https://github.com/twbs/bootstrap/releases
+[Bootstrap Framework SASS Source Files]: https://github.com/twbs/bootstrap-sass
+[jsDelivr]: http://www.jsdelivr.com
+[Less]: http://lesscss.org
+[Sass]: http://sass-lang.com

+ 91 - 0
mydata/themes/bootstrap/docs/Theme-Registry.md

@@ -0,0 +1,91 @@
+<!-- @file Overview of the theme registry workflow in Drupal Bootstrap. -->
+<!-- @defgroup registry -->
+# Theme Registry
+
+- [File Structure](#file-structure)
+- [Theme Functions](#theme-functions)
+- [Theme Process and Preprocess Functions (.vars.php)](#theme-preprocess)
+- [Theme Templates](#theme-templates)
+- [Theme Hook Naming Conventions](#theme-hook-naming-conventions)
+
+## File Structure
+The [Drupal Bootstrap] base theme handles some very complex theme registry
+alterations to assist with the organization and maintenance of its source code.
+
+By leveraging Drupal's ability to include files only when a specific theme hook
+is invoked, this base theme is able to reduce its per page PHP memory footprint.
+It also allows for easier maintenance and organization with as many overrides as
+this base theme implements.
+
+This base theme provides a multitude of [pre]process functions, theme functions
+and templates stored inside the `./bootstrap/templates` folder. The base
+theme will traverse all folders inside this folder as well as a subtheme's
+`./subtheme/templates` folder.
+
+Over time this base theme has grown exponentially and this type of change will
+help ensure future growth, without sacrificing performance. It's an easy and
+hierarchical folder structure based on the module they originated from.
+
+Sub-themes, while not required to do so, can emulate this same type of file
+structure and take advantage of this base theme's unique ability.
+
+Rest assured though, there is no need to structure your sub-theme this way. If
+you feel more comfortable storing everything in your sub-theme's '`template.php`
+file, feel free to do so.
+
+It's highly recommended, however, that you at least understand how the base
+theme structures its functions and templates so you can easily copy them over
+to your sub-theme should the need arise.
+
+## Theme Functions (.func.php) {#theme-functions}
+Theme functions can be be stored in a dedicated file. These files should end in
+a `.func.php` extension where the name of the file relates to the base "theme
+hook" being invoked. For example: the theme hook `breadcrumb` is rendered by
+the `bootstrap_breadcrumb()` theme function located in the
+`./bootstrap/templates/system/breadcrumb.func.php` file.
+
+{.help-block} See related sub-topic below for a list of functions.
+
+## Theme Process and Preprocess Functions (.vars.php) {#theme-preprocess}
+Theme process and preprocess functions can be stored in a dedicated file. These
+files must end with a `.vars.php` extension where the name of the file relates
+to the base "theme hook" being invoked.
+
+For example: the theme hook `page` has both the process function
+`bootstrap_process_page()` and the preprocess function
+`bootstrap_preprocess_page()` which are located in the
+`./bootstrap/templates/system/page.vars.php` file.
+
+This file should also contain any helper functions that are specific to the
+theme hook as well. If a function becomes too large, break it apart so it can
+become more legible.
+
+{.help-block} See related sub-topic below for a list of functions.
+
+## Theme Templates (.tpl.php)  {#theme-templates}
+Theme template files should end with a `.tpl.php` extension where the name of
+the file relates to the base "theme hook" being invoked. For example: the
+template for the theme hook `page` is located at
+`./bootstrap/templates/system/page.tpl.php`.
+
+{.help-block} See related sub-topic below for a list of templates.
+
+## Theme Hook Naming Conventions
+As a general rule, theme hooks must convert all underscores (`_`) to hyphens
+(`-`) for the file name. This can sometimes be especially confusing for some at
+first. Any time a file name has been changed, you must also rebuild the theme
+registry. The easiest way to do this is to "Clear all caches" on the
+`admin/config/development/performance` page.
+
+The exception for this rule would be theme function (`.func.php`) and
+\[pre\]process function (`.vars.php`) files. These file names should only be
+named using the base theme hook (using the general rule).
+
+Theme hook suggestions should not be used in the file name, but rather their
+suggestion functions placed inside the base theme hook `.func.php` or
+`.vars.php` file. An example of this would be the
+`bootstrap_menu_tree__primary()` theme function where the base theme hook is
+`menu_tree` (the hook name before `__`) and located in the
+`./bootstrap/templates/menu/menu-tree.func.php` file.
+
+[Drupal Bootstrap]: https://www.drupal.org/project/bootstrap

+ 156 - 0
mydata/themes/bootstrap/docs/Theme-Settings.md

@@ -0,0 +1,156 @@
+<!-- @file Overview of theme settings for Drupal Bootstrap based themes. -->
+<!-- @defgroup theme_settings -->
+# Theme Settings
+
+To override a setting, open `./subtheme/subtheme.info` and add the following:
+
+`settings[BOOTSTRAP_SETTING] = VALUE`
+
+Where `BOOTSTRAP_SETTING` is the name of the setting and `VALUE` is the value.
+
+---
+
+Below is a complete list of default setting values in the [Drupal Bootstrap]
+base theme:
+
+## Global
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| toggle_name                                      | `1`                       |
+| toggle_search                                    | `1`                       |
+{.table.table-striped}
+
+## Containers
+
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_fluid_container                        | `0`                       |
+{.table.table-striped}
+
+## Buttons
+
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_button_size                            | `''`                      |
+| bootstrap_button_colorize                        | `1`                       |
+| bootstrap_button_iconize                         | `1`                       |
+{.table.table-striped}
+
+## Images
+
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_image_shape                            | `''`                      |
+| bootstrap_image_responsive                       | `1`                       |
+{.table.table-striped}
+
+## Tables
+
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_table_bordered                         | `0`                       |
+| bootstrap_table_condensed                        | `0`                       |
+| bootstrap_table_hover                            | `1`                       |
+| bootstrap_table_striped                          | `1`                       |
+| bootstrap_table_responsive                       | `1`                       |
+{.table.table-striped}
+
+## Breadcrumbs
+
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_breadcrumb                             | `1`                       |
+| bootstrap_breadcrumb_home                        | `0`                       |
+| bootstrap_breadcrumb_title                       | `1`                       |
+{.table.table-striped}
+
+## Navbar
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_navbar_position                        | `''`                      |
+| bootstrap_navbar_inverse                         | `0`                       |
+{.table.table-striped}
+
+## Pager
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_pager_first_and_last                   | `1`                       |
+{.table.table-striped}
+
+## Wells (Regions)
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_region_well-navigation                 | `''`                      |
+| bootstrap_region_well-header                     | `''`                      |
+| bootstrap_region_well-highlighted                | `''`                      |
+| bootstrap_region_well-help                       | `''`                      |
+| bootstrap_region_well-content                    | `''`                      |
+| bootstrap_region_well-sidebar_first              | `'well'`                  |
+| bootstrap_region_well-sidebar_second             | `''`                      |
+| bootstrap_region_well-footer                     | `''`                      |
+{.table.table-striped}
+
+## Anchors
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_anchors_fix                            | `1`                       |
+| bootstrap_anchors_smooth_scrolling               | `1`                       |
+{.table.table-striped}
+
+## Forms
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_forms_required_has_error               | `0`                       |
+| bootstrap_forms_has_error_value_toggle           | `1`                       |
+| bootstrap_forms_smart_descriptions               | `1`                       |
+| bootstrap_forms_smart_descriptions_limit         | `250`                     |
+| bootstrap_forms_smart_descriptions_allowed_tags  | `'b, code, em, i, kbd, span, strong'` |
+{.table.table-striped}
+
+## Popovers
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_popover_enabled                        | `1`                       |
+| bootstrap_popover_animation                      | `1`                       |
+| bootstrap_popover_html                           | `0`                       |
+| bootstrap_popover_placement                      | `'right'`                 |
+| bootstrap_popover_selector                       | `''`                      |
+| [bootstrap_popover_trigger]['hover']             | `0`                       |
+| [bootstrap_popover_trigger]['focus']             | `0`                       |
+| [bootstrap_popover_trigger]['click']             | `'click'`                 |
+| bootstrap_popover_trigger_autoclose              | `1`                       |
+| bootstrap_popover_title                          | `''`                      |
+| bootstrap_popover_content                        | `''`                      |
+| bootstrap_popover_delay                          | `0`                       |
+| bootstrap_popover_container                      | `'body'`                  |
+{.table.table-striped}
+
+## Tooltips
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_tooltip_enabled                        | `1`                       |
+| bootstrap_tooltip_animation                      | `1`                       |
+| bootstrap_tooltip_html                           | `0`                       |
+| bootstrap_tooltip_placement                      | `'auto left'`             |
+| bootstrap_tooltip_selector                       | `''`                      |
+| [bootstrap_tooltip_trigger]['hover']             | `'hover'`                 |
+| [bootstrap_tooltip_trigger]['focus']             | `'focus'`                 |
+| [bootstrap_tooltip_trigger]['click']             | `0`                       |
+| bootstrap_tooltip_delay                          | `0`                       |
+| bootstrap_tooltip_container                      | `'body'`                  |
+{.table.table-striped}
+
+## Advanced
+| Setting                                          | Default value {.col-xs-4} |
+| ------------------------------------------------ | ------------------------- |
+| bootstrap_cdn_provider         | `'jsdelivr'`                                                                |
+| bootstrap_cdn_custom_css       | `'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.css'`     |
+| bootstrap_cdn_custom_css_min   | `'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css'` |
+| bootstrap_cdn_custom_js        | `'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.js'`       |
+| bootstrap_cdn_custom_js_min    | `'https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js'`   |
+| bootstrap_cdn_jsdelivr_version | `'3.4.1'`                                                                   |
+| bootstrap_cdn_jsdelivr_theme   | `'bootstrap'`                                                               |
+{.table.table-striped}
+
+[Drupal Bootstrap]: https://www.drupal.org/project/bootstrap
+[Bootstrap Framework]: https://getbootstrap.com/docs/3.4/

BIN
mydata/themes/bootstrap/favicon.ico


+ 456 - 0
mydata/themes/bootstrap/includes/alter.inc

@@ -0,0 +1,456 @@
+<?php
+
+/**
+ * @file
+ * alter.inc
+ *
+ * Contains various implementations of hook_*_alter().
+ */
+
+/**
+ * Include #pre_render callbacks for elements.
+ */
+bootstrap_include('bootstrap', 'includes/pre-render.inc');
+
+/**
+ * Include #process callbacks for elements.
+ */
+bootstrap_include('bootstrap', 'includes/process.inc');
+
+/**
+ * Implements hook_css_alter().
+ */
+function bootstrap_css_alter(&$css) {
+  // Add CDN assets, if any.
+  if (($provider = bootstrap_setting('cdn_provider')) && ($cdn_assets = bootstrap_get_cdn_assets('css', $provider))) {
+    $cdn_weight = -2.99;
+    foreach ($cdn_assets as $cdn_asset) {
+      $cdn_weight += .01;
+      $css[$cdn_asset] = array(
+        'data' => $cdn_asset,
+        'type' => 'external',
+        'every_page' => TRUE,
+        'media' => 'all',
+        'preprocess' => FALSE,
+        'group' => CSS_THEME,
+        'browsers' => array('IE' => TRUE, '!IE' => TRUE),
+        'weight' => $cdn_weight,
+      );
+    }
+
+    // Add Drupal Bootstrap Styles.
+    // @see https://github.com/unicorn-fail/drupal-bootstrap-styles
+    $version = bootstrap_setting('cdn_' . $provider . '_version') ?: BOOTSTRAP_VERSION;
+    $theme = bootstrap_setting('cdn_' . $provider . '_theme') ?: 'bootstrap';
+    if ($url = _bootstrap_cdn_get_drupal_bootstrap_styles_url($version, $theme)) {
+      $external = url_is_external($url);
+      $css[$url] = array(
+        'data' => $url,
+        'type' => $external ? 'external' : 'file',
+        'every_page' => TRUE,
+        'media' => 'all',
+        'preprocess' => $external ? FALSE : TRUE,
+        'group' => CSS_THEME,
+        'browsers' => array('IE' => TRUE, '!IE' => TRUE),
+        'weight' => -1,
+      );
+    }
+  }
+
+  // Exclude specified CSS files from theme.
+  if ($excludes = bootstrap_get_theme_info(NULL, 'exclude][css')) {
+    $excludes = array_merge($excludes, str_replace('.css', '-rtl.css', $excludes));
+    $css = array_diff_key($css, drupal_map_assoc($excludes));
+  }
+}
+
+/**
+ * Implements hook_element_info_alter().
+ */
+function bootstrap_element_info_alter(&$info) {
+  global $theme_key;
+
+  $cid = "theme_registry:bootstrap:element_info";
+  $cached = array();
+  if (($cache = cache_get($cid)) && !empty($cache->data)) {
+    $cached = $cache->data;
+  }
+
+  $themes = _bootstrap_get_base_themes($theme_key, TRUE);
+  foreach ($themes as $theme) {
+    if (!isset($cached[$theme])) {
+      $cached[$theme] = array();
+      foreach (array_keys($info) as $type) {
+        $element = array();
+
+        // Replace fieldset theme implementations with bootstrap_panel.
+        if (!empty($info[$type]['#theme']) && $info[$type]['#theme'] === 'fieldset') {
+          $element['#bootstrap_replace']['#theme'] = 'bootstrap_panel';
+        }
+        if (!empty($info[$type]['#theme_wrappers']) && array_search('fieldset', $info[$type]['#theme_wrappers']) !== FALSE) {
+          $element['#bootstrap_replace']['#theme_wrappers']['fieldset'] = 'bootstrap_panel';
+        }
+
+        // Setup a default "icon" variable. This allows #icon to be passed
+        // to every template and theme function.
+        // @see https://www.drupal.org/node/2219965
+        $element['#icon'] = NULL;
+        $element['#icon_position'] = 'before';
+
+        $properties = array(
+          '#process' => array(
+            'form_process',
+            'form_process_' . $type,
+          ),
+          '#pre_render' => array(
+            'pre_render',
+            'pre_render_' . $type,
+          ),
+        );
+        foreach ($properties as $property => $callbacks) {
+          foreach ($callbacks as $callback) {
+            $function = $theme . '_' . $callback;
+            if (function_exists($function)) {
+              // Replace direct core function correlation.
+              if (!empty($info[$type][$property]) && array_search($callback, $info[$type][$property]) !== FALSE) {
+                $element['#bootstrap_replace'][$property][$callback] = $function;
+              }
+              // Check for a "form_" prefix instead (for #pre_render).
+              elseif (!empty($info[$type][$property]) && array_search('form_' . $callback, $info[$type][$property]) !== FALSE) {
+                $element['#bootstrap_replace'][$property]['form_' . $callback] = $function;
+              }
+              // Otherwise, append the function.
+              else {
+                $element[$property][] = $function;
+              }
+            }
+          }
+        }
+        $cached[$theme][$type] = $element;
+      }
+
+      // Cache the element information.
+      cache_set($cid, $cached);
+    }
+
+    // Merge in each theme's cached element info.
+    $info = _bootstrap_element_info_array_merge($info, $cached[$theme]);
+  }
+}
+
+/**
+ * Merges the cached element information into the runtime array.
+ *
+ * @param array $info
+ *   The element info array to merge data into.
+ * @param array $cached
+ *   The cached element info data array to merge from.
+ *
+ * @return array
+ *   The altered element info array.
+ */
+function _bootstrap_element_info_array_merge(array $info, array $cached) {
+  foreach ($cached as $type => $element) {
+    $replacement_data = isset($element['#bootstrap_replace']) ? $element['#bootstrap_replace'] : array();
+    unset($element['#bootstrap_replace']);
+    foreach ($element as $property => $data) {
+      if (is_array($data)) {
+        if (!isset($info[$type][$property])) {
+          $info[$type][$property] = array();
+        }
+        // Append the values if not already in the array.
+        foreach ($data as $key => $value) {
+          if (!in_array($value, $info[$type][$property])) {
+            $info[$type][$property][] = $value;
+          }
+        }
+      }
+      // Create the property, if not already set.
+      elseif (!isset($info[$type][$property])) {
+        $info[$type][$property] = $data;
+      }
+    }
+    // Replace data, if necessary.
+    foreach ($replacement_data as $property => $data) {
+      if (is_array($data)) {
+        foreach ($data as $needle => $replacement) {
+          if (!empty($info[$type][$property]) && ($key = array_search($needle, $info[$type][$property])) !== FALSE) {
+            $info[$type][$property][$key] = $replacement;
+          }
+        }
+      }
+      // Replace the property with the new data.
+      else {
+        $info[$type][$property] = $data;
+      }
+    }
+  }
+
+  // Return the altered element info array.
+  return $info;
+}
+
+/**
+ * Implements hook_field_widget_form_alter().
+ */
+function bootstrap_field_widget_form_alter(&$element, &$form_state, $context) {
+  $widget_type = isset($context['instance']['widget']['type']) ? $context['instance']['widget']['type'] : NULL;
+  if ($widget_type === 'image_image') {
+    foreach (element_children($element) as $child) {
+      $element[$child]['#process'][] = '_bootstrap_image_field_widget_process';
+    }
+  }
+}
+
+/**
+ * Implements above #process callback.
+ */
+function _bootstrap_image_field_widget_process($element, &$form_state, $form) {
+  // Core explicitly sets #theme_wrappers to an empty array for the upload
+  // element (perhaps for styling reasons?). Thus, bootstrap_form_element() is
+  // invoked, preventing any necessary logic from executing. To achieve the
+  // same goal and keep backwards compatibility, reset the theme wrapper back
+  // and indicating that the wrapper shouldn't be printed.
+  $element['upload']['#theme_wrappers'][] = 'form_element__image_widget';
+  $element['upload']['#form_element_wrapper'] = FALSE;
+
+  // Unfortunately, core also doesn't set #access on the appropriate elements
+  // until way too late (ironically, because of #ajax). Instead of calling
+  // file_managed_file_pre_render(), just mimic the same #access logic, but
+  // using #default_value instead of #value since the ajax request populates
+  // #value.
+  $value = empty($element['#default_value']['fid']);
+  if (!$value) {
+    $element['upload']['#access'] = FALSE;
+    $element['upload_button']['#access'] = FALSE;
+  }
+  // If we don't already have a file, there is nothing to remove.
+  else {
+    $element['remove_button']['#access'] = FALSE;
+  }
+
+  // Make the upload file element an input group with a button.
+  $element['upload']['#input_group_button'] = $value;
+
+  return $element;
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function bootstrap_form_alter(array &$form, array &$form_state = array(), $form_id = NULL) {
+  if ($form_id) {
+    switch ($form_id) {
+      case 'system_theme_settings':
+        // Create vertical tabs for global settings (provided by core or other
+        // contrib modules).
+        if (!isset($form['global'])) {
+          $form['global'] = array(
+            '#type' => 'vertical_tabs',
+            '#weight' => -9,
+          );
+          if (!empty($form_state['build_info']['args'][0])) {
+            $form['global']['#prefix'] = '<h2><small>' . t('Override Global Settings') . '</small></h2>';
+          }
+        }
+
+        // Iterate over all child elements and check to see if they should be
+        // moved in the global vertical tabs.
+        $global_children = element_children($form);
+        foreach ($global_children as $child) {
+          if (isset($form[$child]['#type']) && $form[$child]['#type'] === 'fieldset' && !isset($form[$child]['#group'])) {
+            $form[$child]['#group'] = 'global';
+          }
+        }
+        break;
+
+      case 'search_form':
+        // Add a clearfix class so the results don't overflow onto the form.
+        $form['#attributes']['class'][] = 'clearfix';
+
+        // Remove container-inline from the container classes.
+        $form['basic']['#attributes']['class'] = array();
+
+        // Hide the default button from display.
+        $form['basic']['submit']['#attributes']['class'][] = 'element-invisible';
+
+        // Implement a theme wrapper to add a submit button containing a search
+        // icon directly after the input element.
+        $form['basic']['keys']['#theme_wrappers'] = array('bootstrap_search_form_wrapper');
+        $form['basic']['keys']['#title'] = '';
+        $form['basic']['keys']['#attributes']['placeholder'] = t('Search');
+        break;
+
+      case 'search_block_form':
+        $form['#attributes']['class'][] = 'form-search';
+
+        $form['search_block_form']['#title'] = '';
+        $form['search_block_form']['#attributes']['placeholder'] = t('Search');
+
+        // Hide the default button from display and implement a theme wrapper
+        // to add a submit button containing a search icon directly after the
+        // input element.
+        $form['actions']['submit']['#attributes']['class'][] = 'element-invisible';
+        $form['search_block_form']['#theme_wrappers'] = array('bootstrap_search_form_wrapper');
+
+        // Apply a clearfix so the results don't overflow onto the form.
+        $form['#attributes']['class'][] = 'content-search';
+        break;
+
+      case 'image_style_form':
+        $form['effects']['new']['new']['#input_group_button'] = TRUE;
+        break;
+
+      case 'path_admin_filter_form':
+        $form['basic']['filter']['#input_group_button'] = TRUE;
+        break;
+    }
+
+  }
+}
+
+/**
+ * Implements hook_js_alter().
+ */
+function bootstrap_js_alter(&$js) {
+  // Exclude specified JavaScript files from theme.
+  $excludes = bootstrap_get_theme_info(NULL, 'exclude][js');
+
+  $theme_path = drupal_get_path('theme', 'bootstrap');
+
+  // Add or replace JavaScript files when matching paths are detected.
+  // Replacement files must begin with '_', like '_node.js'.
+  $files = _bootstrap_file_scan_directory($theme_path . '/js', '/\.js$/');
+  foreach ($files as $file) {
+    $path = str_replace($theme_path . '/js/', '', $file->uri);
+    // Detect if this is a replacement file.
+    $replace = FALSE;
+    if (preg_match('/^[_]/', $file->filename)) {
+      $replace = TRUE;
+      $path = dirname($path) . '/' . preg_replace('/^[_]/', '', $file->filename);
+    }
+    $matches = array();
+    if (preg_match('/^modules\/([^\/]*)/', $path, $matches)) {
+      if (!module_exists($matches[1])) {
+        continue;
+      }
+      else {
+        $path = str_replace('modules/' . $matches[1], drupal_get_path('module', $matches[1]), $path);
+      }
+    }
+    // Path should always exist to either add or replace JavaScript file.
+    if (!empty($js[$path])) {
+      // Replace file.
+      if ($replace) {
+        $js[$file->uri] = $js[$path];
+        $js[$file->uri]['data'] = $file->uri;
+        unset($js[$path]);
+      }
+      // Add file.
+      else {
+        $js[$file->uri] = drupal_js_defaults($file->uri);
+        $js[$file->uri]['group'] = JS_THEME;
+      }
+    }
+  }
+
+  // Ensure jQuery Once is always loaded.
+  // @see https://www.drupal.org/node/2149561
+  if (empty($js['misc/jquery.once.js'])) {
+    $jquery_once = drupal_get_library('system', 'jquery.once');
+    $js['misc/jquery.once.js'] = $jquery_once['js']['misc/jquery.once.js'];
+    $js['misc/jquery.once.js'] += drupal_js_defaults('misc/jquery.once.js');
+  }
+
+  // Always add bootstrap.js last.
+  $bootstrap = $theme_path . '/js/bootstrap.js';
+  $js[$bootstrap] = drupal_js_defaults($bootstrap);
+  $js[$bootstrap]['group'] = JS_THEME;
+  $js[$bootstrap]['scope'] = 'footer';
+
+  if (!empty($excludes)) {
+    $js = array_diff_key($js, drupal_map_assoc($excludes));
+  }
+
+  // Add Bootstrap settings.
+  $js['settings']['data'][]['bootstrap'] = array(
+    'anchorsFix' => bootstrap_setting('anchors_fix'),
+    'anchorsSmoothScrolling' => bootstrap_setting('anchors_smooth_scrolling'),
+    'formHasError' => (int) bootstrap_setting('forms_has_error_value_toggle'),
+    'popoverEnabled' => bootstrap_setting('popover_enabled'),
+    'popoverOptions' => array(
+      'animation' => (int) bootstrap_setting('popover_animation'),
+      'html' => (int) bootstrap_setting('popover_html'),
+      'placement' => bootstrap_setting('popover_placement'),
+      'selector' => bootstrap_setting('popover_selector'),
+      'trigger' => implode(' ', array_filter(array_values((array) bootstrap_setting('popover_trigger')))),
+      'triggerAutoclose' => (int) bootstrap_setting('popover_trigger_autoclose'),
+      'title' => bootstrap_setting('popover_title'),
+      'content' => bootstrap_setting('popover_content'),
+      'delay' => (int) bootstrap_setting('popover_delay'),
+      'container' => bootstrap_setting('popover_container'),
+    ),
+    'tooltipEnabled' => bootstrap_setting('tooltip_enabled'),
+    'tooltipOptions' => array(
+      'animation' => (int) bootstrap_setting('tooltip_animation'),
+      'html' => (int) bootstrap_setting('tooltip_html'),
+      'placement' => bootstrap_setting('tooltip_placement'),
+      'selector' => bootstrap_setting('tooltip_selector'),
+      'trigger' => implode(' ', array_filter(array_values((array) bootstrap_setting('tooltip_trigger')))),
+      'delay' => (int) bootstrap_setting('tooltip_delay'),
+      'container' => bootstrap_setting('tooltip_container'),
+    ),
+  );
+
+  // Add CDN assets, if any.
+  if ($cdn_assets = bootstrap_get_cdn_assets('js')) {
+    $cdn_weight = -99.99;
+    foreach ($cdn_assets as $cdn_asset) {
+      $cdn_weight += .01;
+      $js[$cdn_asset] = drupal_js_defaults($cdn_asset);
+      $js[$cdn_asset]['type'] = 'external';
+      $js[$cdn_asset]['every_page'] = TRUE;
+      $js[$cdn_asset]['weight'] = $cdn_weight;
+    }
+  }
+}
+
+/**
+ * Implements hook_icon_bundle_list_alter().
+ */
+function bootstrap_icon_bundle_list_alter(&$build, $bundle) {
+  if (bootstrap_setting('tooltip_enabled')) {
+    foreach ($build as &$icon) {
+      $icon['#attributes']['data-toggle'] = 'tooltip';
+      $icon['#attributes']['data-placement'] = 'bottom';
+    }
+  }
+}
+
+/**
+ * Implements hook_menu_local_tasks_alter().
+ */
+function bootstrap_menu_local_tasks_alter(&$data, &$router_item, $root_path) {
+  if (!empty($data['actions']['output'])) {
+    $items = array();
+    foreach ($data['actions']['output'] as $item) {
+      $items[] = array(
+        'data' => $item,
+      );
+    }
+    $data['actions']['output'] = array(
+      '#theme' => 'item_list__action_links',
+      '#items' => $items,
+      '#attributes' => array(
+        'class' => array('action-links'),
+      ),
+    );
+  }
+}
+
+/**
+ * Implements hook_js_callback_filter_xss_alter().
+ */
+function bootstrap_js_callback_filter_xss_alter(array &$allowed_tags = array()) {
+  $allowed_tags[] = 'button';
+}

+ 661 - 0
mydata/themes/bootstrap/includes/cdn.inc

@@ -0,0 +1,661 @@
+<?php
+
+/**
+ * @file
+ * cdn.inc
+ *
+ * Provides necessary CDN integration.
+ */
+
+define('BOOTSTRAP_CDN_PROVIDER_PATH', 'public://bootstrap/cdn_providers');
+
+/**
+ * Retrieves JSON from a URI.
+ *
+ * @param string $url
+ *   The URI to retrieve JSON from.
+ * @param array $options
+ *   The options to pass to the HTTP client.
+ * @param \Exception|null $exception
+ *   The exception thrown if there was an error, passed by reference.
+ *
+ * @return array
+ *   The requested JSON array.
+ */
+function _bootstrap_cdn_provider_request_json($url, array $options = array(), &$exception = NULL) {
+  $json = array();
+
+  $options += array(
+    'method' => 'GET',
+    'headers' => array(
+      'User-Agent' => 'Drupal Bootstrap 7.x-3.x (https://www.drupal.org/project/bootstrap)',
+    ),
+  );
+
+  try {
+    $response = drupal_http_request($url, $options);
+    if (!empty($response->error)) {
+      throw new \Exception($response->error, $response->code);
+    }
+    if ($response->code == 200) {
+      $json = drupal_json_decode($response->data) ?: array();
+    }
+  }
+  catch (\Exception $e) {
+    $exception = $e;
+  }
+
+  return $json;
+}
+
+/**
+ * Retrieves the Drupal Bootstrap Styles to use with CDN assets.
+ *
+ * @param string $version
+ *   A specific version to use. If not set, the currently set CDN Provider
+ *   version will be used.
+ * @param string $theme
+ *   A specific theme to use. If not set, the currently set CDN Provider
+ *   theme will be used.
+ *
+ * @return string|false
+ *   The URL to the styles or FALSE if it doesn't exist.
+ */
+function _bootstrap_cdn_get_drupal_bootstrap_styles_url($version = NULL, $theme = NULL) {
+  global $theme_key;
+  static $styles;
+
+  if (!isset($provider)) {
+    $provider = bootstrap_setting('cdn_provider', NULL, 'bootstrap', 'jsdelivr');
+  }
+
+  if (!isset($version)) {
+    $version = bootstrap_setting('cdn_' . $provider . '_version') ?: BOOTSTRAP_VERSION;
+  }
+
+  if (!isset($theme)) {
+    $theme = bootstrap_setting('cdn_' . $provider . '_theme') ?: 'bootstrap';
+  }
+
+
+  $cid = "theme_registry:$theme_key:drupal_bootstrap_styles";
+  $min = variable_get('preprocess_css', FALSE) ? '.min' : '';
+  $key = "$provider:$version:$theme$min";
+
+  if (!isset($styles)) {
+    // Allow sites to manually specify a custom path or URL.
+    if ($data = variable_get('drupal_bootstrap_styles')) {
+      $styles = array($key => $data);
+    }
+    // Otherwise, attempt to load cached database data.
+    else {
+      $styles = ($cache = cache_get($cid)) && !empty($cache->data) ? $cache->data : array();
+    }
+  }
+
+  if (!isset($styles[$key])) {
+    // Determine the latest @unicorn-fail/drupal-bootstrap-styles version.
+    if (!isset($styles['versions'])) {
+      $json = _bootstrap_cdn_provider_request_json('https://data.jsdelivr.com/v1/package/npm/@unicorn-fail/drupal-bootstrap-styles');
+      $json += array('versions' => array());
+      natsort($json['versions']);
+      $styles['versions'] = $json['versions'];
+    }
+
+    // Latest version should be the last entry.
+    $pkg_version = end($styles['versions']);
+
+    // Retrieve the list of files from the actual distributed API JSON file in
+    // @unicorn-fail/drupal-bootstrap-styles (note the sub-domain difference).
+    if (!isset($styles["$pkg_version:files"])) {
+      $json = _bootstrap_cdn_provider_request_json("https://cdn.jsdelivr.net/npm/@unicorn-fail/drupal-bootstrap-styles@$pkg_version/dist/api.json");
+      $json += array('files' => array());
+      $styles["$pkg_version:files"] = array_filter($json['files'], function ($file) {
+        return !!preg_match('`^/?dist/(\d+\.\d+\.\d+)/7.x-3.x`', $file['name']);
+      });
+    }
+
+    $styles[$key] = FALSE;
+    $theme = $theme === 'bootstrap' || $theme === 'bootstrap_theme' ? '' : "-$theme";
+    foreach ($styles["$pkg_version:files"] as $file) {
+      if (!empty($file['name']) && $file['name'] === "/dist/$version/7.x-3.x/drupal-bootstrap$theme$min.css") {
+        $filename = !empty($file['symlink']) ? $file['symlink'] : $file['name'];
+        $styles[$key] = "https://cdn.jsdelivr.net/npm/@unicorn-fail/drupal-bootstrap-styles@$pkg_version$filename";
+        break;
+      }
+    }
+
+    // Now cache the styles.
+    cache_set($cid, $styles);
+  }
+
+  return $styles[$key];
+}
+
+/**
+ * Retrieves a list of available CDN providers for the Bootstrap framework.
+ *
+ * @param string $provider
+ *   A specific provider data to return.
+ * @param bool $reset
+ *   Toggle determining whether or not to reset the database cache.
+ *
+ * @return array|false
+ *   An associative array of CDN providers, keyed by their machine name if
+ *   $provider is not set. If $provider is set and exists, its individual
+ *   data array will be returned. If $provider is set and the data does not
+ *   exist then FALSE will be returned.
+ */
+function bootstrap_cdn_provider($provider = NULL, $reset = FALSE) {
+  $original_provider = $provider;
+
+  // Use the advanced drupal_static() pattern, since this is called very often.
+  static $drupal_static_fast;
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['providers'] = &drupal_static(__FUNCTION__);
+  }
+  $providers = &$drupal_static_fast['providers'];
+  if ($reset || !isset($providers)) {
+    $provider_path = BOOTSTRAP_CDN_PROVIDER_PATH;
+    file_prepare_directory($provider_path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+
+    $cid = 'theme_registry:bootstrap:cdn_providers';
+    if (($cached = cache_get($cid)) && !empty($cached->data)) {
+      $providers = $cached->data;
+    }
+    if ($reset || !isset($providers)) {
+      $providers = array(
+        'custom' => array(
+          'title' => t('Custom'),
+        ),
+        'jsdelivr' => array(
+          'title' => t('jsDelivr'),
+          'description' => t('<p><a href="!jsdelivr" target="_blank">jsDelivr</a> is a free multi-CDN infrastructure that uses <a href="!maxcdn" target="_blank">MaxCDN</a>, <a href="!cloudflare" target="_blank">Cloudflare</a> and many others to combine their powers for the good of the open source community... <a href="!jsdelivr_about" target="_blank">read more</a></p>', array(
+            '!jsdelivr' => 'https://www.jsdelivr.com',
+            '!jsdelivr_about' => 'https://www.jsdelivr.com/about',
+            '!maxcdn' => 'https://www.maxcdn.com',
+            '!cloudflare' => 'https://www.cloudflare.com',
+          )),
+        ),
+      );
+
+      // Defaults properties each provider must have.
+      $defaults = array(
+        'api' => NULL,
+        'css' => array(),
+        'description' => NULL,
+        'error' => FALSE,
+        'js' => array(),
+        'imported' => FALSE,
+        'min' => array(
+          'css' => array(),
+          'js' => array(),
+        ),
+        'title' => NULL,
+      );
+
+      // Process the providers.
+      foreach ($providers as $name => &$data) {
+        $data += $defaults;
+        $data['name'] = $name;
+        if (empty($name)) {
+          continue;
+        }
+
+        // Use manually imported API data, if it exists.
+        $request = NULL;
+        if (!empty($data['api']) && file_exists("$provider_path/$name.json") && ($imported_data = file_get_contents("$provider_path/$name.json"))) {
+          $data['imported'] = TRUE;
+          $request = new stdClass();
+          $request->code = '200';
+          $request->data = $imported_data;
+        }
+        // Otherwise, attempt to request API data if the provider has specified
+        // an "api" URL to use.
+        elseif (!empty($data['api'])) {
+          $request = drupal_http_request($data['api']);
+        }
+
+        // Skip alter (processing) if using backported CDN Provider logic.
+        if ($instance = _bootstrap_backport_cdn_provider(NULL, $name)) {
+          // Go ahead and use its description and label though.
+          $data['description'] = $instance->getDescription();
+          $data['title'] = $instance->getLabel();
+          continue;
+        }
+
+        // Alter the specific provider.
+        $function = 'bootstrap_bootstrap_cdn_provider_' . $name . '_alter';
+        if (function_exists($function)) {
+          $function($data, $request);
+        }
+      }
+      cache_set($cid, $providers);
+    }
+  }
+  if (isset($original_provider)) {
+    if (!isset($providers[$original_provider])) {
+      return FALSE;
+    }
+    return $providers[$original_provider];
+  }
+  return $providers;
+}
+
+/**
+ * Callback for jsDelivr CDN.
+ *
+ * @param array $provider
+ *   The provider data array, passed by reference.
+ * @param \stdClass $request
+ *   The raw request object, if the provider specified an "api" URL to retrieve
+ *   data prior to this alter hook being called. It is up to whatever
+ *   implements these hooks to parse the requested data.
+ */
+function bootstrap_bootstrap_cdn_provider_jsdelivr_alter(array &$provider, \stdClass $request = NULL) {
+  $provider['versions'] = array();
+  $provider['themes'] = array();
+
+  $json = array();
+  foreach (array('bootstrap', 'bootswatch') as $package) {
+    $data = array('name' => $package, 'assets' => array());
+    $latest = '0.0.0';
+    $versions = array();
+    $packageJson = _bootstrap_cdn_provider_request_json("https://data.jsdelivr.com/v1/package/npm/$package") + array('versions' => array());
+    foreach ($packageJson['versions'] as $key => $version) {
+      // Skip irrelevant versions.
+      if (!preg_match('/^' . substr(BOOTSTRAP_VERSION, 0, 1) . '\.\d+\.\d+$/', $version)) {
+        continue;
+      }
+      $versionJson = _bootstrap_cdn_provider_request_json("https://data.jsdelivr.com/v1/package/npm/$package@$version/flat");
+
+      // Skip empty files.
+      if (empty($versionJson['files'])) {
+        continue;
+      }
+
+      $versions[] = $version;
+      if (version_compare($latest, $version) === -1) {
+        $latest = $version;
+      }
+
+      $asset = array('files' => array(), 'version' => $version);
+      foreach ($versionJson['files'] as $file) {
+        // Skip old bootswatch file structure.
+        if ($package === 'bootswatch' && preg_match('`^/2|/bower_components`', $file['name'], $matches)) {
+          continue;
+        }
+        preg_match('`([^/]*)/bootstrap(-theme)?(\.min)?\.(js|css)$`', $file['name'], $matches);
+        if (!empty($matches[1]) && !empty($matches[4])) {
+          $asset['files'][] = $file['name'];
+        }
+      }
+      $data['assets'][] = $asset;
+    }
+    $data['lastversion'] = $latest;
+    $data['versions'] = $versions;
+    $json[] = $data;
+  }
+
+  // Extract the raw asset files from the JSON data for each framework.
+  $libraries = array();
+  if ($json) {
+    foreach ($json as $data) {
+      if ($data['name'] === 'bootstrap' || $data['name'] === 'bootswatch') {
+        foreach ($data['assets'] as $asset) {
+          if (preg_match('/^' . BOOTSTRAP_VERSION_MAJOR . '\.\d\.\d$/', $asset['version'])) {
+            $libraries[$data['name']][$asset['version']] = $asset['files'];
+          }
+        }
+      }
+    }
+  }
+
+  // If the main bootstrap library could not be found, then provide defaults.
+  if (!isset($libraries['bootstrap'])) {
+    $provider['error'] = TRUE;
+    $provider['versions'][BOOTSTRAP_VERSION] = BOOTSTRAP_VERSION;
+    $provider['themes'][BOOTSTRAP_VERSION] = array(
+      'bootstrap' => array(
+        'title' => t('Bootstrap'),
+        'css' => array('https://cdn.jsdelivr.net/npm/bootstrap@' . BOOTSTRAP_VERSION . '/dist/css/bootstrap.css'),
+        'js' => array('https://cdn.jsdelivr.net/npm/bootstrap@' . BOOTSTRAP_VERSION . '/dist/js/bootstrap.js'),
+        'min' => array(
+          'css' => array('https://cdn.jsdelivr.net/npm/bootstrap@' . BOOTSTRAP_VERSION . '/dist/css/bootstrap.min.css'),
+          'js' => array('https://cdn.jsdelivr.net/npm/bootstrap@' . BOOTSTRAP_VERSION . '/dist/js/bootstrap.min.js'),
+        ),
+      ),
+    );
+    return;
+  }
+
+  // Populate the provider array with the versions and themes available.
+  foreach (array_keys($libraries['bootstrap']) as $version) {
+    $provider['versions'][$version] = $version;
+
+    if (!isset($provider['themes'][$version])) {
+      $provider['themes'][$version] = array();
+    }
+
+    // Extract Bootstrap themes.
+    $provider['themes'][$version] = drupal_array_merge_deep($provider['themes'][$version], _bootstrap_cdn_provider_jsdelivr_extract_themes($libraries['bootstrap'][$version], "https://cdn.jsdelivr.net/npm/bootstrap@$version"));
+
+    // Extract Bootswatch themes.
+    if (isset($libraries['bootswatch'][$version])) {
+      $provider['themes'][$version] = drupal_array_merge_deep($provider['themes'][$version], _bootstrap_cdn_provider_jsdelivr_extract_themes($libraries['bootswatch'][$version], "https://cdn.jsdelivr.net/npm/bootswatch@$version"));
+    }
+  }
+
+  // Post process the themes to fill in any missing assets.
+  foreach (array_keys($provider['themes']) as $version) {
+    foreach (array_keys($provider['themes'][$version]) as $theme) {
+      // Some themes actually require Bootstrap framework assets to still
+      // function properly.
+      if ($theme !== 'bootstrap') {
+        foreach (array('css', 'js') as $type) {
+          // Bootswatch themes include the Bootstrap framework in their CSS.
+          // Skip the CSS portions.
+          if ($theme !== 'bootstrap_theme' && $type === 'css') {
+            continue;
+          }
+          if (!isset($provider['themes'][$version][$theme][$type]) && !empty($provider['themes'][$version]['bootstrap'][$type])) {
+            $provider['themes'][$version][$theme][$type] = array();
+          }
+          $provider['themes'][$version][$theme][$type] = drupal_array_merge_deep($provider['themes'][$version]['bootstrap'][$type], $provider['themes'][$version][$theme][$type]);
+          if (!isset($provider['themes'][$version][$theme]['min'][$type]) && !empty($provider['themes'][$version]['bootstrap']['min'][$type])) {
+            $provider['themes'][$version][$theme]['min'][$type] = array();
+          }
+          $provider['themes'][$version][$theme]['min'][$type] = drupal_array_merge_deep($provider['themes'][$version]['bootstrap']['min'][$type], $provider['themes'][$version][$theme]['min'][$type]);
+        }
+      }
+      // Some themes do not have a non-minified version, clone them to the
+      // "normal" css/js arrays to ensure that the theme still loads if
+      // aggregation (minification) is disabled.
+      foreach (array('css', 'js') as $type) {
+        if (!isset($provider['themes'][$version][$theme][$type]) && isset($provider['themes'][$version][$theme]['min'][$type])) {
+          $provider['themes'][$version][$theme][$type] = $provider['themes'][$version][$theme]['min'][$type];
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Extracts theme information from files provided by the jsDelivr API.
+ *
+ * This will place the raw files into proper "css", "js" and "min" arrays
+ * (if they exist) and prepends them with a base URL provided.
+ *
+ * @param array $files
+ *   An array of files to process.
+ * @param string $base_url
+ *   The base URL each one of the $files are relative to, this usually
+ *   should also include the version path prefix as well.
+ *
+ * @return array
+ *   An associative array containing the following keys, if there were
+ *   matching files found:
+ *   - css
+ *   - js
+ *   - min:
+ *     - css
+ *     - js
+ */
+function _bootstrap_cdn_provider_jsdelivr_extract_themes(array $files, $base_url = '') {
+  $themes = array();
+  foreach ($files as $file) {
+    preg_match('`([^/]*)/bootstrap(-theme)?(\.min)?\.(js|css)$`', $file, $matches);
+    if (!empty($matches[1]) && !empty($matches[4])) {
+      $path = $matches[1];
+      $min = $matches[3];
+      $filetype = $matches[4];
+
+      // Determine the "theme" name.
+      if ($path === 'css' || $path === 'js') {
+        $theme = 'bootstrap';
+        $title = t('Bootstrap');
+      }
+      else {
+        $theme = $path;
+        $title = ucfirst($path);
+      }
+      if ($matches[2]) {
+        $theme = 'bootstrap_theme';
+        $title = t('Bootstrap Theme');
+      }
+
+      $themes[$theme]['title'] = $title;
+      if ($min) {
+        $themes[$theme]['min'][$filetype][] = "$base_url/" . ltrim($file, '/');
+      }
+      else {
+        $themes[$theme][$filetype][] = "$base_url/" . ltrim($file, '/');
+      }
+    }
+  }
+  return $themes;
+}
+
+/**
+ * Callback for Custom CDN assets.
+ */
+function bootstrap_bootstrap_cdn_provider_custom_assets_alter(&$provider, $theme = NULL) {
+  foreach (array('css', 'js') as $type) {
+    if ($setting = bootstrap_setting('cdn_custom_' . $type, $theme)) {
+      $provider[$type][] = $setting;
+    }
+    if ($setting = bootstrap_setting('cdn_custom_' . $type . '_min', $theme)) {
+      $provider['min'][$type][] = $setting;
+    }
+  }
+}
+
+/**
+ * Callback for jsDelivr CDN assets.
+ */
+function bootstrap_bootstrap_cdn_provider_jsdelivr_assets_alter(&$provider, $theme = NULL) {
+  $error = !empty($provider['error']);
+  $version = $error ? BOOTSTRAP_VERSION : bootstrap_setting('cdn_jsdelivr_version', $theme);
+  $theme = $error ? 'bootstrap' : bootstrap_setting('cdn_jsdelivr_theme', $theme);
+  if (isset($provider['themes'][$version][$theme])) {
+    $provider = drupal_array_merge_deep($provider, $provider['themes'][$version][$theme]);
+  }
+}
+
+/**
+ * Custom callback for CDN provider settings.
+ *
+ * @see bootstrap_form_system_theme_settings_alter()
+ */
+function bootstrap_cdn_provider_settings_form(&$form, &$form_state, $theme) {
+  // Retrieve the provider from form values or the setting.
+  $provider = isset($form_state['values']['bootstrap_cdn_provider']) ? $form_state['values']['bootstrap_cdn_provider'] : bootstrap_setting('cdn_provider', $theme);
+
+  // Intercept possible manual import of API data via AJAX callback.
+  if (isset($form_state['clicked_button']['#value']) && $form_state['clicked_button']['#value'] === t('Save provider data')) {
+    $provider_path = BOOTSTRAP_CDN_PROVIDER_PATH;
+    file_prepare_directory($provider_path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    $provider_data = isset($form_state['values']['bootstrap_cdn_provider_import_data']) ? $form_state['values']['bootstrap_cdn_provider_import_data'] : FALSE;
+    $provider_file = "$provider_path/$provider.json";
+    if ($provider_data) {
+      file_unmanaged_save_data($provider_data, $provider_file, FILE_EXISTS_REPLACE);
+    }
+    elseif ($provider_file && file_exists($provider_file)) {
+      file_unmanaged_delete($provider_file);
+    }
+    bootstrap_cdn_provider(NULL, TRUE);
+  }
+
+  $description_label = t('NOTE');
+  $description = t('Using one of the "CDN Provider" options below is the preferred method for loading Bootstrap CSS and JS on simpler sites that do not use a site-wide CDN. Using a "CDN Provider" for loading Bootstrap, however, does mean that it depends on a third-party service. There is no obligation or commitment by these third-parties that guarantees any up-time or service quality. If you need to customize Bootstrap and have chosen to compile the source code locally (served from this site), you must disable the "CDN Provider" option below by choosing "- None -" and alternatively enable a site-wide CDN implementation. All local (served from this site) versions of Bootstrap will be superseded by any enabled "CDN Provider" below. <strong>Do not do both</strong>.');
+  $form['advanced']['cdn'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('CDN (Content Delivery Network)'),
+    '#description' => '<div class="alert alert-info messages warning"><strong>' . $description_label . ':</strong> ' . $description . '</div>',
+    '#collapsible' => TRUE,
+    '#collapsed' => !$provider,
+  );
+
+  $providers = bootstrap_cdn_provider();
+  $options = array();
+  foreach ($providers as $key => $data) {
+    $options[$key] = $data['title'];
+  }
+  $form['advanced']['cdn']['bootstrap_cdn_provider'] = array(
+    '#type' => 'select',
+    '#title' => t('CDN Provider'),
+    '#default_value' => $provider,
+    '#empty_value' => '',
+    '#options' => $options,
+  );
+
+  // Render each provider.
+  foreach ($providers as $name => $data) {
+    $form['advanced']['cdn']['provider'][$name] = array(
+      '#type' => 'container',
+      '#prefix' => '<div id="bootstrap-cdn-provider-' . $name . '">',
+      '#suffix' => '</div>',
+      '#states' => array(
+        'visible' => array(
+          ':input[name="bootstrap_cdn_provider"]' => array('value' => $name),
+        ),
+      ),
+    );
+    $element = &$form['advanced']['cdn']['provider'][$name];
+
+    $element['description']['#markup'] = '<div class="lead">' . $data['description'] . '</div>';
+
+    // Indicate there was an error retrieving the provider's API data.
+    if (!empty($data['error']) || !empty($data['imported'])) {
+      if (!empty($data['error'])) {
+        $description_label = t('ERROR');
+        $description = t('Unable to reach or parse the data provided by the @title API. Ensure the server this website is hosted on is able to initiate HTTP requests via <a href="!drupal_http_request" target="_blank">drupal_http_request()</a>. If the request consistently fails, it is likely that there are certain PHP functions that have been disabled by the hosting provider for security reasons. It is possible to manually copy and paste the contents of the following URL into the "Imported @title data" section below.<br /><br /><a href="!provider_api" target="_blank">!provider_api</a>.', array(
+          '@title' => $data['title'],
+          '!provider_api' => $data['api'],
+          '!drupal_http_request' => 'https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_http_request/7',
+        ));
+        $element['#prefix'] .= '<div class="alert alert-danger messages error"><strong>' . $description_label . ':</strong> ' . $description . '</div>';
+      }
+      $element['import'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Imported @title data', array(
+          '@title' => $data['title'],
+        )),
+        '#description' => t('The provider will attempt to parse the data entered here each time it is saved. If no data has been entered, any saved files associated with this provider will be removed and the provider will again attempt to request the API data normally through the following URL: <a href="!provider_api" target="_blank">!provider_api</a>.', array(
+          '!provider_api' => $data['api'],
+        )),
+        '#weight' => 10,
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+      );
+      $element['import']['bootstrap_cdn_provider_import_data'] = array(
+        '#type' => 'textarea',
+        '#default_value' => file_exists(BOOTSTRAP_CDN_PROVIDER_PATH . '/' . $name . '.json') ? file_get_contents(BOOTSTRAP_CDN_PROVIDER_PATH . '/' . $name . '.json') : NULL,
+      );
+      $element['import']['submit'] = array(
+        '#type' => 'submit',
+        '#value' => t('Save provider data'),
+        '#executes_submit_callback' => FALSE,
+        '#ajax' => array(
+          'callback' => 'bootstrap_cdn_provider_settings_form_ajax_reload_provider',
+          'wrapper' => 'bootstrap-cdn-provider-' . $name,
+        ),
+      );
+    }
+
+    // Alter the specific provider.
+    $function = 'bootstrap_bootstrap_cdn_provider_' . $name . '_settings_form_alter';
+    if (function_exists($function)) {
+      $function($element, $form_state, $data, $theme);
+    }
+  }
+}
+
+/**
+ * AJAX callback for reloading CDN provider elements.
+ */
+function bootstrap_cdn_provider_settings_form_ajax_reload_provider($form, $form_state) {
+  return $form['advanced']['cdn']['provider'][$form_state['values']['bootstrap_cdn_provider']];
+}
+
+/**
+ * Implements hook_bootstrap_cdn_provider_PROVIDER_settings_form_alter().
+ */
+function bootstrap_bootstrap_cdn_provider_custom_settings_form_alter(&$element, &$form_state, $provider = array(), $theme = NULL) {
+  foreach (array('css', 'js') as $type) {
+    $setting = bootstrap_setting('cdn_custom_' . $type, $theme);
+    $setting_min = bootstrap_setting('cdn_custom_' . $type . '_min', $theme);
+    $element['bootstrap_cdn_custom_' . $type] = array(
+      '#type' => 'textfield',
+      '#title' => t('Bootstrap @type URL', array(
+        '@type' => drupal_strtoupper($type),
+      )),
+      '#description' => t('It is best to use protocol relative URLs (i.e. without http: or https:) here as it will allow more flexibility if the need ever arises.'),
+      '#default_value' => $setting,
+    );
+    $element['bootstrap_cdn_custom_' . $type . '_min'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Minified Bootstrap @type URL', array(
+        '@type' => drupal_strtoupper($type),
+      )),
+      '#description' => t('Additionally, you can provide the minimized version of the file. It will be used instead if site aggregation is enabled.'),
+      '#default_value' => $setting_min,
+    );
+  }
+}
+
+/**
+ * Implements hook_bootstrap_cdn_provider_PROVIDER_settings_form_alter().
+ */
+function bootstrap_bootstrap_cdn_provider_jsdelivr_settings_form_alter(&$element, &$form_state, $provider = array(), $theme = NULL) {
+  $version = isset($form_state['values']['bootstrap_cdn_jsdelivr_version']) ? $form_state['values']['bootstrap_cdn_jsdelivr_version'] : bootstrap_setting('cdn_jsdelivr_version', $theme);
+
+  // Use backported CDN Provider logic from 8.x-3.x.
+  if ($instance = _bootstrap_backport_cdn_provider($theme, $provider['name'])) {
+    $versions = $instance->getCdnVersions();
+    $themes = array();
+    foreach ($instance->getCdnThemes($version) as $name => $data) {
+      $themes[$name] = $data['title'];
+    }
+  }
+  else {
+    $versions = isset($provider['versions']) ? $provider['versions'] : array();
+    $themes = array();
+    if (isset($provider['themes'][$version])) {
+      foreach ($provider['themes'][$version] as $_theme => $data) {
+        $themes[$_theme] = $data['title'];
+      }
+    }
+  }
+
+  $element['bootstrap_cdn_jsdelivr_version'] = array(
+    '#type' => 'select',
+    '#title' => t('Version'),
+    '#options' => $versions,
+    '#default_value' => $version,
+    '#ajax' => array(
+      'callback' => 'bootstrap_cdn_provider_settings_form_ajax_reload_provider',
+      'wrapper' => 'bootstrap-cdn-provider-jsdelivr',
+    ),
+  );
+  if (empty($provider['error']) && empty($provider['imported'])) {
+    $element['bootstrap_cdn_jsdelivr_version']['#description'] = t('These versions are automatically populated by the @provider API upon cache clear and newer versions may appear over time. It is highly recommended the version that the site was built with stays at that version. Until a newer version has been properly tested for updatability by the site maintainer, you should not arbitrarily "update" just because there is a newer version. This can cause many inconsistencies and undesired effects with an existing site.', array(
+      '@provider' => $provider['title'],
+    ));
+  }
+
+  // Themes.
+  $element['bootstrap_cdn_jsdelivr_theme'] = array(
+    '#type' => 'select',
+    '#title' => t('Theme'),
+    '#description' => t('Choose the example <a href="!bootstrap_theme" target="_blank">Bootstrap Theme</a> provided by Bootstrap or one of the many, many <a href="!bootswatch" target="_blank">Bootswatch</a> themes!', array(
+      '!bootswatch' => 'https://bootswatch.com',
+      '!bootstrap_theme' => 'https://getbootstrap.com/docs/3.3/examples/theme/',
+    )),
+    '#default_value' => bootstrap_setting('cdn_jsdelivr_theme', $theme),
+    '#options' => $themes,
+    '#empty_option' => t('Bootstrap (default)'),
+    '#empty_value' => 'bootstrap',
+    '#suffix' => '<div id="bootstrap-theme-preview"></div>',
+  );
+}

+ 37 - 0
mydata/themes/bootstrap/includes/cdn/Custom.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\bootstrap\Backport\Plugin\Provider;
+
+/**
+ * The "custom" CDN provider plugin.
+ *
+ * Note: this class is a backport from the 8.x-3.x code base.
+ *
+ * @see https://drupal-bootstrap.org/api/bootstrap/namespace/Drupal%21bootstrap%21Plugin%21Provider/8
+ *
+ * @ingroup plugins_provider
+ */
+class Custom extends ProviderBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $pluginId = 'custom';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function discoverCdnAssets($version, $theme) {
+    $assets = array();
+    foreach (array('css', 'js') as $type) {
+      if ($setting = bootstrap_setting('cdn_custom_' . $type)) {
+        $assets[$type][] = $setting;
+      }
+      if ($setting = bootstrap_setting('cdn_custom_' . $type . '_min')) {
+        $assets['min'][$type][] = $setting;
+      }
+    }
+    return $assets;
+  }
+
+}

+ 325 - 0
mydata/themes/bootstrap/includes/cdn/JsDelivr.php

@@ -0,0 +1,325 @@
+<?php
+
+namespace Drupal\bootstrap\Backport\Plugin\Provider;
+
+/**
+ * The "jsdelivr" CDN provider plugin.
+ *
+ * Note: this class is a backport from the 8.x-3.x code base.
+ *
+ * @see https://drupal-bootstrap.org/api/bootstrap/namespace/Drupal%21bootstrap%21Plugin%21Provider/8
+ *
+ * @ingroup plugins_provider
+ */
+class JsDelivr extends ProviderBase {
+
+  protected $pluginId = 'jsdelivr';
+
+  /**
+   * The base API URL.
+   *
+   * @var string
+   */
+  const BASE_API_URL = 'https://data.jsdelivr.com/v1/package/npm';
+
+  /**
+   * The base CDN URL.
+   *
+   * @var string
+   */
+  const BASE_CDN_URL = 'https://cdn.jsdelivr.net/npm';
+
+  /**
+   * A list of latest versions, keyed by NPM package name.
+   *
+   * @var string[]
+   */
+  protected $latestVersion = array();
+
+  /**
+   * A list of themes, keyed by NPM package name.
+   *
+   * @var array[]
+   */
+  protected $themes = array();
+
+  /**
+   * A list of versions, keyed by NPM package name.
+   *
+   * @var array[]
+   */
+  protected $versions = array();
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return t('<p><a href="!jsdelivr" target="_blank">jsDelivr</a> is a free multi-CDN infrastructure that uses <a href="!maxcdn" target="_blank">MaxCDN</a>, <a href="!cloudflare" target="_blank">Cloudflare</a> and many others to combine their powers for the good of the open source community... <a href="!jsdelivr_about" target="_blank">read more</a></p>', array(
+      '!jsdelivr' => 'https://www.jsdelivr.com',
+      '!jsdelivr_about' => 'https://www.jsdelivr.com/about',
+      '!maxcdn' => 'https://www.maxcdn.com',
+      '!cloudflare' => 'https://www.cloudflare.com',
+    ));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLabel() {
+    return t('jsDelivr');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function discoverCdnAssets($version, $theme = 'bootstrap') {
+    $themes = $this->getCdnThemes($version);
+    return isset($themes[$theme]) ? $themes[$theme] : array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnThemes($version = NULL) {
+    if (!isset($version)) {
+      $version = $this->getCdnVersion();
+    }
+    if (!isset($this->themes[$version])) {
+      $instance = $this;
+      $this->themes[$version] = $this->cacheGet('themes.' . static::escapeDelimiter($version), array(), function ($themes) use ($version, $instance) {
+        return $instance->getCdnThemePhp53Callback($themes, $version);
+      });
+    }
+    return $this->themes[$version];
+  }
+
+  /**
+   * Callback to get around PHP 5.3's limitation of automatic binding of $this.
+   *
+   * @see https://www.drupal.org/project/bootstrap/issues/3054809
+   *
+   * {@inheritdoc}
+   */
+  public function getCdnThemePhp53Callback($themes, $version) {
+    foreach (array('bootstrap', 'bootswatch') as $package) {
+      $mappedVersion = $this->mapVersion($version, $package);
+      $files = $this->requestApiV1($package, $mappedVersion);
+      $themes = $this->parseThemes($files, $package, $mappedVersion, $themes);
+    }
+    return $themes;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnVersions($package = 'bootstrap') {
+    if (!isset($this->versions[$package])) {
+      $instance = $this;
+      $this->versions[$package] = $this->cacheGet("versions.$package", array(), function ($versions) use ($package, $instance) {
+        return $instance->getCdnVersionsPhp53Callback($versions, $package);
+      });
+    }
+    return $this->versions[$package];
+  }
+
+  /**
+   * Callback to get around PHP 5.3's limitation of automatic binding of $this.
+   *
+   * @see https://www.drupal.org/project/bootstrap/issues/3054809
+   *
+   * {@inheritdoc}
+   */
+  public function getCdnVersionsPhp53Callback($versions, $package) {
+    $json = $this->requestApiV1($package) + array('versions' => array());
+    foreach ($json['versions'] as $version) {
+      // Skip irrelevant versions.
+      if (!preg_match('/^' . substr(BOOTSTRAP_VERSION, 0, 1) . '\.\d+\.\d+$/', $version)) {
+        continue;
+      }
+      $versions[$version] = $version;
+    }
+    return $versions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapVersion($version, $package = NULL) {
+    // While the Bootswatch project attempts to maintain version parity with
+    // Bootstrap, it doesn't always happen. This causes issues when the system
+    // expects a 1:1 version match between Bootstrap and Bootswatch.
+    // @see https://github.com/thomaspark/bootswatch/issues/892#ref-issue-410070082
+    if ($package === 'bootswatch') {
+      switch ($version) {
+        // This version is "broken" because of jsDelivr's API limit.
+        case '3.4.1':
+          $version = '3.4.0';
+          break;
+
+        // This version doesn't exist.
+        case '3.1.1':
+          $version = '3.2.0';
+          break;
+      }
+    }
+    return $version;
+  }
+
+  /**
+   * Parses JSON from the API and retrieves valid files.
+   *
+   * @param array $json
+   *   The JSON data to parse.
+   *
+   * @return array
+   *   An array of files parsed from provided JSON data.
+   */
+  protected function parseFiles(array $json) {
+    // Immediately return if malformed.
+    if (!isset($json['files']) || !is_array($json['files'])) {
+      return array();
+    }
+
+    $files = array();
+    foreach ($json['files'] as $file) {
+      // Skip old bootswatch file structure.
+      if (preg_match('`^/2|/bower_components`', $file['name'], $matches)) {
+        continue;
+      }
+      preg_match('`([^/]*)/bootstrap(-theme)?(\.min)?\.(js|css)$`', $file['name'], $matches);
+      if (!empty($matches[1]) && !empty($matches[4])) {
+        $files[] = $file['name'];
+      }
+    }
+    return $files;
+  }
+
+  /**
+   * Extracts assets from files provided by the jsDelivr API.
+   *
+   * This will place the raw files into proper "css", "js" and "min" arrays
+   * (if they exist) and prepends them with a base URL provided.
+   *
+   * @param array $files
+   *   An array of files to process.
+   * @param string $package
+   *   The base URL each one of the $files are relative to, this usually
+   *   should also include the version path prefix as well.
+   * @param string $version
+   *   A specific version to use.
+   * @param array $themes
+   *   An existing array of themes. This is primarily used when building a
+   *   complete list of themes.
+   *
+   * @return array
+   *   An associative array containing the following keys, if there were
+   *   matching files found:
+   *   - css
+   *   - js
+   *   - min:
+   *     - css
+   *     - js
+   */
+  protected function parseThemes(array $files, $package, $version, array $themes = array()) {
+    $baseUrl = static::BASE_CDN_URL . "/$package@$version";
+    foreach ($files as $file) {
+      preg_match('`([^/]*)/bootstrap(-theme)?(\.min)?\.(js|css)$`', $file, $matches);
+      if (!empty($matches[1]) && !empty($matches[4])) {
+        $path = $matches[1];
+        $min = $matches[3];
+        $filetype = $matches[4];
+
+        // Determine the "theme" name.
+        if ($path === 'css' || $path === 'js') {
+          $theme = 'bootstrap';
+          $title = (string) t('Bootstrap');
+        }
+        else {
+          $theme = $path;
+          $title = ucfirst($path);
+        }
+        if ($matches[2]) {
+          $theme = 'bootstrap_theme';
+          $title = (string) t('Bootstrap Theme');
+        }
+
+        $themes[$theme]['title'] = $title;
+        if ($min) {
+          $themes[$theme]['min'][$filetype][] = "$baseUrl/" . ltrim($file, '/');
+        }
+        else {
+          $themes[$theme][$filetype][] = "$baseUrl/" . ltrim($file, '/');
+        }
+      }
+    }
+
+    // Post process the themes to fill in any missing assets.
+    foreach (array_keys($themes) as $theme) {
+      // Some themes do not have a non-minified version, clone them to the
+      // "normal" css/js arrays to ensure that the theme still loads if
+      // aggregation (minification) is disabled.
+      foreach (array('css', 'js') as $type) {
+        if (!isset($themes[$theme][$type]) && isset($themes[$theme]['min'][$type])) {
+          $themes[$theme][$type] = $themes[$theme]['min'][$type];
+        }
+      }
+
+      // Prepend the main Bootstrap styles before the Bootstrap theme.
+      if ($theme === 'bootstrap_theme') {
+        if (isset($themes['bootstrap']['css'])) {
+          $themes[$theme]['css'] = array_unique(array_merge($themes['bootstrap']['css'], isset($themes[$theme]['css']) ? $themes[$theme]['css'] : array()));
+        }
+        if (isset($themes['bootstrap']['min']['css'])) {
+          $themes[$theme]['min']['css'] = array_unique(array_merge($themes['bootstrap']['min']['css'], isset($themes[$theme]['min']['css']) ? $themes[$theme]['min']['css'] : array()));
+        }
+      }
+
+      // Populate missing JavaScript.
+      if (!isset($themes[$theme]['js']) && isset($themes['bootstrap']['js'])) {
+        $themes[$theme]['js'] = $themes['bootstrap']['js'];
+      }
+      if (!isset($themes[$theme]['min']['js']) && isset($themes['bootstrap']['min']['js'])) {
+        $themes[$theme]['min']['js'] = $themes['bootstrap']['min']['js'];
+      }
+    }
+
+    return $themes;
+  }
+
+  /**
+   * Requests JSON from jsDelivr's API V1.
+   *
+   * @param string $package
+   *   The NPM package being requested.
+   * @param string $version
+   *   A specific version of $package to request. If not provided, a list of
+   *   available versions will be returned.
+   *
+   * @return array
+   *   The JSON data from the API.
+   */
+  protected function requestApiV1($package, $version = NULL) {
+    $url = static::BASE_API_URL . "/$package";
+
+    // If no version was passed, then all versions are returned.
+    if (!$version) {
+      return $this->requestJson($url);
+    }
+
+    $json = $this->requestJson("$url@$version/flat");
+
+    // If bootstrap JSON could not be returned, provide defaults.
+    if (!$json && $package === 'bootstrap') {
+      return array(
+        '/dist/css/bootstrap.css',
+        '/dist/js/bootstrap.js',
+        '/dist/css/bootstrap.min.css',
+        '/dist/js/bootstrap.min.js',
+      );
+    }
+
+    // Parse the files from JSON.
+    return $this->parseFiles($json);
+  }
+
+}

+ 375 - 0
mydata/themes/bootstrap/includes/cdn/ProviderBase.php

@@ -0,0 +1,375 @@
+<?php
+
+namespace Drupal\bootstrap\Backport\Plugin\Provider;
+
+/**
+ * CDN provider base class.
+ *
+ * Note: this class is a backport from the 8.x-3.x code base.
+ *
+ * @see https://drupal-bootstrap.org/api/bootstrap/namespace/Drupal%21bootstrap%21Plugin%21Provider/8
+ *
+ * @ingroup plugins_provider
+ */
+abstract class ProviderBase {
+
+  /**
+   * The plugin_id.
+   *
+   * @var string
+   */
+  protected $pluginId;
+
+  /**
+   * The currently set CDN assets.
+   *
+   * @var array
+   */
+  protected $cdnAssets;
+
+  /**
+   * The current theme name.
+   *
+   * @var string
+   */
+  protected $themeName;
+
+  /**
+   * The versions supplied by the CDN provider.
+   *
+   * @var array
+   */
+  protected $versions;
+
+  /**
+   * ProviderBase constructor.
+   */
+  public function __construct() {
+    $this->themeName = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : '';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function alterFrameworkLibrary(array &$framework, $min = NULL) {
+    // In Drupal 7, CSS and JS are separated into individual hooks and alters,
+    // so this has the potential to be invoked at a minimum of 3 times.
+    static $drupal_static_fast;
+    if (!isset($drupal_static_fast)) {
+      // Attempt to retrieve CDN assets from a sort of permanent cached in the
+      // theme settings. This is primarily used to avoid unnecessary API requests
+      // and speed up the process during a cache rebuild. Theme settings are used
+      // as they persist through cache rebuilds. In order to prevent stale data,
+      // a hash is used based on current CDN settings and this "permacache" is
+      // reset at least once a week regardless.
+      // @see https://www.drupal.org/project/bootstrap/issues/3031415
+      $cdnCache = variable_get('bootstrap_cdn_cache') ?: array();
+
+      // Reset cache if expired.
+      if (isset($cdnCache['expire']) && (empty($cdnCache['expire']) || REQUEST_TIME > $cdnCache['expire'])) {
+        $cdnCache = array();
+      }
+
+      // Set expiration date (1 week by default).
+      if (!isset($cdnCache['expire'])) {
+        $cdnCache['expire'] = REQUEST_TIME + variable_get('bootstrap_cdn_cache_expire', 604800);
+      }
+
+      $cdnVersion = $this->getCdnVersion();
+      $cdnTheme = $this->getCdnTheme();
+
+      // Cache not found.
+      $cdnHash = drupal_hash_base64("{$this->pluginId}:$cdnTheme:$cdnVersion");
+      if (!isset($cdnCache[$cdnHash])) {
+        // Retrieve assets and reset cache (should only cache one at a time).
+        $cdnCache = array(
+          'expire' => $cdnCache['expire'],
+          $cdnHash => $this->getCdnAssets($cdnVersion, $cdnTheme),
+        );
+        variable_set('bootstrap_cdn_cache', $cdnCache);
+      }
+
+      // Immediately return if there are no theme CDN assets to use.
+      if (empty($cdnCache[$cdnHash])) {
+        return;
+      }
+
+      // Retrieve the system performance config.
+      if (!isset($min)) {
+        $min = array(
+          'css' => variable_get('preprocess_css', FALSE),
+          'js' => variable_get('preprocess_js', FALSE),
+        );
+      }
+      else {
+        $min = array('css' => !!$min, 'js' => !!$min);
+      }
+
+      // Iterate over each type.
+      $assets = array();
+      foreach (array('css', 'js') as $type) {
+        $files = !empty($min[$type]) && isset($cdnCache[$cdnHash]['min'][$type]) ? $cdnCache[$cdnHash]['min'][$type] : (isset($cdnCache[$cdnHash][$type]) ? $cdnCache[$cdnHash][$type] : array());
+        foreach ($files as $asset) {
+          $assets[$type][$asset] = array('data' => $asset, 'type' => 'external');
+        }
+      }
+
+      // Merge the assets into the library info.
+      $drupal_static_fast = drupal_array_merge_deep_array(array($assets, $framework));
+
+      // Override the framework version with the CDN version that is being used.
+      $drupal_static_fast['version'] = $cdnVersion;
+    }
+
+    $framework = $drupal_static_fast;
+  }
+
+  /**
+   * Retrieves a value from the CDN provider cache.
+   *
+   * @param string $key
+   *   The name of the item to retrieve. Note: this can be in the form of dot
+   *   notation if the value is nested in an array.
+   * @param mixed $default
+   *   Optional. The default value to return if $key is not set.
+   * @param callable $builder
+   *   Optional. If provided, a builder will be invoked when there is no cache
+   *   currently set.
+   *
+   * @return mixed
+   *   The cached value if it's set or the value supplied to $default if not.
+   */
+  protected function cacheGet($key, $default = NULL, $builder = NULL) {
+    $cid = $this->getCacheId();
+    $cache = cache_get($cid);
+    $data = $cache && isset($cache->data) && is_array($cache->data) ? $cache->data : array();
+    $parts = static::splitDelimiter($key);
+    $value = drupal_array_get_nested_value($data, $parts, $key_exists);
+
+    // Build the cache.
+    if (!$key_exists && is_callable($builder)) {
+      $value = $builder($default);
+      if (!isset($value)) {
+        $value = $default;
+      }
+      drupal_array_set_nested_value($data, $parts, $value);
+      cache_set($cid, $data);
+      return $value;
+    }
+
+    return $key_exists ? $value : $default;
+  }
+
+  /**
+   * Sets a value in the CDN provider cache.
+   *
+   * @param string $key
+   *   The name of the item to set. Note: this can be in the form of dot
+   *   notation if the value is nested in an array.
+   * @param mixed $value
+   *   Optional. The value to set.
+   */
+  protected function cacheSet($key, $value = NULL) {
+    $cid = $this->getCacheId();
+    $cache = cache_get($cid);
+    $data = $cache && isset($cache->data) && is_array($cache->data) ? $cache->data : array();
+    $parts = static::splitDelimiter($key);
+    drupal_array_set_nested_value($data, $parts, $value);
+    cache_set($cid, $data);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function discoverCdnAssets($version, $theme) {
+    return array();
+  }
+
+  /**
+   * Retrieves the unique cache identifier for the CDN provider.
+   *
+   * @return string
+   *   The CDN provider cache identifier.
+   */
+  protected function getCacheId() {
+    return "theme_registry:{$this->themeName}:provider:{$this->pluginId}";
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnAssets($version = NULL, $theme = NULL) {
+    if (!isset($version)) {
+      $version = $this->getCdnVersion();
+    }
+    if (!isset($theme)) {
+      $theme = $this->getCdnTheme();
+    }
+
+    if (!isset($this->cdnAssets)) {
+      $this->cdnAssets = $this->cacheGet('cdn.assets', array());
+    }
+
+    if (!isset($this->cdnAssets[$version][$theme])) {
+      $escapedVersion = static::escapeDelimiter($version);
+      $instance = $this;
+      $this->cdnAssets[$version][$theme] = $this->cacheGet("cdn.assets.$escapedVersion.$theme", array(), function () use ($version, $theme, $instance) {
+        return $instance->discoverCdnAssets($version, $theme);
+      });
+    }
+
+    return $this->cdnAssets[$version][$theme];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnTheme() {
+    return bootstrap_setting("cdn_{$this->pluginId}_theme") ?: 'bootstrap';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnThemes($version = NULL) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnVersion() {
+    return bootstrap_setting("cdn_{$this->pluginId}_version") ?: BOOTSTRAP_VERSION;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCdnVersions() {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return '';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLabel() {
+    return t(ucfirst($this->pluginId));
+  }
+
+  /**
+   * Allows providers a way to map a version to a different version.
+   *
+   * @param string $version
+   *   The version to map.
+   *
+   * @return string
+   *   The mapped version.
+   */
+  protected function mapVersion($version) {
+    return $version;
+  }
+
+  /**
+   * Retrieves JSON from a URI.
+   *
+   * @param string $uri
+   *   The URI to retrieve JSON from.
+   * @param array $options
+   *   The options to pass to the HTTP client.
+   * @param \Exception|null $exception
+   *   The exception thrown if there was an error, passed by reference.
+   *
+   * @return array
+   *   The requested JSON array.
+   */
+  protected function requestJson($uri, array $options = array(), &$exception = NULL) {
+    $json = array();
+
+    $options += array(
+      'method' => 'GET',
+      'headers' => array(
+        'User-Agent' => 'Drupal Bootstrap 7.x-3.x (https://www.drupal.org/project/bootstrap)',
+      ),
+    );
+
+    try {
+      $response = drupal_http_request($uri, $options);
+      if (!empty($response->error)) {
+        throw new \Exception("$uri: {$response->error}", $response->code);
+      }
+      if ($response->code >= 200 && $response->code < 400) {
+        $json = drupal_json_decode($response->data) ?: array();
+      }
+      else {
+        throw new \Exception("$uri: Invalid response", $response->code);
+      }
+    }
+    catch (\Exception $e) {
+      $exception = $e;
+    }
+
+    return $json;
+  }
+
+  /**
+   * Escapes a delimiter in a string.
+   *
+   * Note: this is primarily useful in situations where dot notation is used
+   * where the values also contain dots, like in a semantic version string.
+   *
+   * @param string $string
+   *   The string to search in.
+   * @param string $delimiter
+   *   The delimiter to escape.
+   *
+   * @return string
+   *   The escaped string.
+   *
+   * @see \Drupal\bootstrap\Plugin\Provider\ProviderBase::splitDelimiter()
+   */
+  public static function escapeDelimiter($string, $delimiter = '.') {
+    return str_replace($delimiter, "\\$delimiter", $string);
+  }
+
+  /**
+   * Splits a string by a specified delimiter, allowing them to be escaped.
+   *
+   * Note: this is primarily useful in situations where dot notation is used
+   * where the values also contain dots, like in a semantic version string.
+   *
+   * @param string $string
+   *   The string to split into parts.
+   * @param string $delimiter
+   *   The delimiter used to split the string.
+   * @param bool $escapable
+   *   Flag indicating whether the $delimiter can be escaped using a backward
+   *   slash (\).
+   *
+   * @return array
+   *   An array of strings, split where the specified $delimiter was present.
+   *
+   * @see \Drupal\bootstrap\Plugin\Provider\ProviderBase::escapeDelimiter()
+   * @see https://stackoverflow.com/a/6243797
+   */
+  public static function splitDelimiter($string, $delimiter = '.', $escapable = TRUE) {
+    if (!$escapable) {
+      return explode($delimiter, $string);
+    }
+
+    // Split based on delimiter.
+    $parts = preg_split('~\\\\' . preg_quote($delimiter, '~') . '(*SKIP)(*FAIL)|\.~s', $string);
+
+    // Iterate over the parts and remove backslashes from delimiters.
+    return array_map(function ($string) use ($delimiter) {
+      return str_replace("\\$delimiter", $delimiter, $string);
+    }, $parts);
+  }
+
+}

+ 1557 - 0
mydata/themes/bootstrap/includes/common.inc

@@ -0,0 +1,1557 @@
+<?php
+
+/**
+ * @file
+ * List of common helper functions for use in Drupal Bootstrap based themes.
+ */
+
+/**
+ * @defgroup utility Utilities
+ *
+ * List of common helper functions for use in Drupal Bootstrap based themes.
+ *
+ * @{
+ */
+
+define('BOOTSTRAP_VERSION_MAJOR', 3);
+define('BOOTSTRAP_VERSION_MINOR', 4);
+define('BOOTSTRAP_VERSION_PATCH', 1);
+define('BOOTSTRAP_VERSION', BOOTSTRAP_VERSION_MAJOR . '.' . BOOTSTRAP_VERSION_MINOR . '.' . BOOTSTRAP_VERSION_PATCH);
+
+/**
+ * Converts an element description into a tooltip based on certain criteria.
+ *
+ * @param array $element
+ *   An element render array, passed by reference.
+ * @param array $target
+ *   The target element render array the tooltip is to be attached to, passed
+ *   by reference. If not set, it will default to the $element passed.
+ * @param bool $input_only
+ *   Toggle determining whether or not to only convert input elements.
+ * @param int $length
+ *   The length of characters to determine if description is "simple".
+ */
+function bootstrap_element_smart_description(array &$element, array &$target = NULL, $input_only = TRUE, $length = NULL) {
+  // Determine if tooltips are enabled.
+  static $enabled;
+  if (!isset($enabled)) {
+    $enabled = bootstrap_setting('tooltip_enabled') && bootstrap_setting('forms_smart_descriptions');
+  }
+
+  // Immediately return if "simple" tooltip descriptions are not enabled.
+  if (!$enabled) {
+    return;
+  }
+
+  // Allow a different element to attach the tooltip.
+  if (!isset($target)) {
+    $target = &$element;
+  }
+
+  // Retrieve the length limit for smart descriptions.
+  if (!isset($length)) {
+    $length = (int) bootstrap_setting('forms_smart_descriptions_limit');
+    // Disable length checking by setting it to FALSE if empty.
+    if (empty($length)) {
+      $length = FALSE;
+    }
+  }
+
+  // Retrieve the allowed tags for smart descriptions. This is primarily used
+  // for display purposes only (i.e. non-UI/UX related elements that wouldn't
+  // require a user to "click", like a link).
+  $allowed_tags = array_filter(array_unique(array_map('trim', explode(',', bootstrap_setting('forms_smart_descriptions_allowed_tags') . ''))));
+
+  // Disable length checking by setting it to FALSE if empty.
+  if (empty($allowed_tags)) {
+    $allowed_tags = FALSE;
+  }
+
+  $html = FALSE;
+  $type = !empty($element['#type']) ? $element['#type'] : FALSE;
+
+  // Return if element or target shouldn't have "simple" tooltip descriptions.
+  if (($input_only && !isset($target['#input']))
+    // Ignore text_format elements.
+    // @see https://www.drupal.org/node/2478339
+    || $type === 'text_format'
+
+    // Ignore if the actual element has no #description set.
+    || empty($element['#description'])
+
+    // Ignore if the target element already has a "data-toggle" attribute set.
+    || !empty($target['#attributes']['data-toggle'])
+
+    // Ignore if the target element is #disabled.
+    || isset($target['#disabled'])
+
+    // Ignore if either the actual element or target element has an explicit
+    // #smart_description property set to FALSE.
+    || (isset($element['#smart_description']) && !$element['#smart_description'])
+    || (isset($target['#smart_description']) && !$target['#smart_description'])
+
+    // Ignore if the description is not "simple".
+    || !_bootstrap_is_simple_string($element['#description'], $length, $allowed_tags, $html)
+  ) {
+    // Set the both the actual element and the target element
+    // #smart_description property to FALSE.
+    $element['#smart_description'] = FALSE;
+    $target['#smart_description'] = FALSE;
+    return;
+  }
+
+  // Default property (on the element itself).
+  $property = 'attributes';
+
+  // Add the tooltip to the #label_attributes property for 'checkbox'
+  // and 'radio' elements.
+  if ($type === 'checkbox' || $type === 'radio') {
+    $property = 'label_attributes';
+  }
+  // Add the tooltip to the #wrapper_attributes property for 'checkboxes'
+  // and 'radios' elements.
+  elseif ($type === 'checkboxes' || $type === 'radios') {
+    $property = 'wrapper_attributes';
+  }
+  // Add the tooltip to the #input_group_attributes property for elements
+  // that have valid input groups set.
+  elseif ((!empty($element['#field_prefix']) || !empty($element['#field_suffix'])) && (!empty($element['#input_group']) || !empty($element['#input_group_button']))) {
+    $property = 'input_group_attributes';
+  }
+
+  // Retrieve the proper attributes array.
+  $attributes = &_bootstrap_get_attributes($target, $property);
+
+  // Set the tooltip attributes.
+  $attributes['title'] = $allowed_tags !== FALSE ? filter_xss($element['#description'], $allowed_tags) : $element['#description'];
+  $attributes['data-toggle'] = 'tooltip';
+  if ($html || $allowed_tags === FALSE) {
+    $attributes['data-html'] = 'true';
+  }
+
+  // Remove the element description so it isn't (re-)rendered later.
+  unset($element['#description']);
+}
+
+/**
+ * Retrieves a plugin that uses backported CDN Provider logic from 8.x-3.x.
+ *
+ * @param string $theme
+ *   The name of a given theme; defaults to the currently active theme.
+ *
+ * @return \Drupal\bootstrap\Backport\Plugin\Provider\ProviderBase|false
+ *   A CDN Provider instance or FALSE if provider cannot use backported code.
+ */
+function _bootstrap_backport_cdn_provider($theme = NULL, $provider = NULL) {
+  /** @var \Drupal\bootstrap\Backport\Plugin\Provider\ProviderBase[] $providers */
+  static $providers = array();
+
+  // If no key is given, use the current theme if we can determine it.
+  if (!isset($theme)) {
+    $theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : '';
+  }
+
+  if (!isset($provider)) {
+    $provider = bootstrap_setting('cdn_provider', $theme);
+  }
+
+  if (!isset($providers[$theme][$provider])) {
+    $providers[$theme][$provider]  = FALSE;
+    if (bootstrap_setting('cdn_use_backported_code', $theme, 'bootstrap', TRUE)) {
+      if ($provider === 'jsdelivr') {
+        require_once __DIR__ . '/cdn/ProviderBase.php';
+        require_once __DIR__ . '/cdn/JsDelivr.php';
+        $providers[$theme][$provider] = new \Drupal\bootstrap\Backport\Plugin\Provider\JsDelivr();
+      }
+      elseif ($provider === 'custom') {
+        require_once __DIR__ . '/cdn/ProviderBase.php';
+        require_once __DIR__ . '/cdn/Custom.php';
+        $providers[$theme][$provider] = new \Drupal\bootstrap\Backport\Plugin\Provider\Custom();
+      }
+    }
+  }
+
+  return $providers[$theme][$provider];
+}
+
+/**
+ * Retrieves CDN assets for the active provider, if any.
+ *
+ * @param string|array $type
+ *   The type of asset to retrieve: "css" or "js", defaults to an array
+ *   array containing both if not set.
+ * @param string $provider
+ *   The name of a specific CDN provider to use, defaults to the active provider
+ *   set in the theme settings.
+ * @param string $theme
+ *   The name of a specific theme the settings should be retrieved from,
+ *   defaults to the active theme.
+ *
+ * @return array
+ *   If $type is a string or an array with only one (1) item in it, the assets
+ *   are returned as an indexed array of files. Otherwise, an associative array
+ *   is returned keyed by the type.
+ */
+function bootstrap_get_cdn_assets($type = NULL, $provider = NULL, $theme = NULL) {
+  bootstrap_include('bootstrap', 'includes/cdn.inc');
+
+  $original_type = $type;
+  $assets = array();
+  $types = array();
+
+  // If no type is set, return all CSS and JS.
+  if (!isset($type)) {
+    $types = array('css', 'js');
+  }
+  elseif (isset($type)) {
+    if (!is_array($type)) {
+      $type = array($type);
+    }
+    $types = $type;
+  }
+
+  // Ensure default arrays exist for the requested types.
+  foreach ($types as $type) {
+    $assets[$type] = array();
+  }
+
+  // Retrieve the CDN provider from the theme.
+  if (!isset($provider)) {
+    $provider = bootstrap_setting('cdn_provider', $theme);
+  }
+
+  // Immediately return if there's no provider set.
+  if (empty($provider)) {
+    return array();
+  }
+
+  // Check if the backported 8.x-3.x jsDelivr code should be used.
+  if ($provider = _bootstrap_backport_cdn_provider($theme, $provider)) {
+    $framework = array();
+    $provider->alterFrameworkLibrary($framework);
+    $assets = array_map(function ($data) {
+      $assets = array();
+      foreach ($data as $info) {
+        if (isset($info['data'])) {
+          $assets[] = $info['data'];
+        }
+      }
+      return $assets;
+    }, array_intersect_key($framework, array_flip($types)));
+  }
+  // Otherwise, use the legacy CDN provider code.
+  else {
+    if (!empty($provider) && ($data = bootstrap_cdn_provider($provider))) {
+      // Alter the assets based on provider.
+      $function = 'bootstrap_bootstrap_cdn_provider_' . $provider . '_assets_alter';
+      if (function_exists($function)) {
+        $function($data, $theme);
+      }
+      // Iterate over each type.
+      foreach ($types as $type) {
+        if (variable_get("preprocess_$type", FALSE) && !empty($data['min'][$type])) {
+          $assets[$type] = $data['min'][$type];
+        }
+        elseif (!empty($data[$type])) {
+          $assets[$type] = $data[$type];
+        }
+      }
+    }  }
+
+  return is_string($original_type) ? $assets[$original_type] : $assets;
+}
+
+/**
+ * Return information from the .info file of a theme (and possible base themes).
+ *
+ * @param string $theme_key
+ *   The machine name of the theme.
+ * @param string $key
+ *   The key name of the item to return from the .info file. This value can
+ *   include "][" to automatically attempt to traverse any arrays.
+ * @param bool $base_themes
+ *   Recursively search base themes, defaults to TRUE.
+ *
+ * @return string|array|false
+ *   A string or array depending on the type of value and if a base theme also
+ *   contains the same $key, FALSE if no $key is found.
+ */
+function bootstrap_get_theme_info($theme_key = NULL, $key = NULL, $base_themes = TRUE) {
+  // If no $theme_key is given, use the current theme if we can determine it.
+  if (!isset($theme_key)) {
+    $theme_key = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : FALSE;
+  }
+  if ($theme_key) {
+    $themes = list_themes();
+    if (!empty($themes[$theme_key])) {
+      $theme = $themes[$theme_key];
+      // If a key name was specified, return just that array.
+      if ($key) {
+        $value = FALSE;
+        // Recursively add base theme values.
+        if ($base_themes && isset($theme->base_themes)) {
+          foreach (array_keys($theme->base_themes) as $base_theme) {
+            $value = bootstrap_get_theme_info($base_theme, $key);
+          }
+        }
+        if (!empty($themes[$theme_key])) {
+          $info = $themes[$theme_key]->info;
+          // Allow array traversal.
+          $keys = explode('][', $key);
+          foreach ($keys as $parent) {
+            if (isset($info[$parent])) {
+              $info = $info[$parent];
+            }
+            else {
+              $info = FALSE;
+            }
+          }
+          if (is_array($value)) {
+            if (!empty($info)) {
+              if (!is_array($info)) {
+                $info = array($info);
+              }
+              $value = drupal_array_merge_deep($value, $info);
+            }
+          }
+          else {
+            if (!empty($info)) {
+              if (empty($value)) {
+                $value = $info;
+              }
+              else {
+                if (!is_array($value)) {
+                  $value = array($value);
+                }
+                if (!is_array($info)) {
+                  $info = array($info);
+                }
+                $value = drupal_array_merge_deep($value, $info);
+              }
+            }
+          }
+        }
+        return $value;
+      }
+      // If no info $key was specified, just return the entire info array.
+      return $theme->info;
+    }
+  }
+  return FALSE;
+}
+
+/**
+ * Includes a theme file.
+ *
+ * @param string $theme
+ *   Name of the theme to use for base path.
+ * @param string $path
+ *   Path relative to $theme.
+ *
+ * @return string|false
+ *   The absolute path to the include file or FALSE if it doesn't exist.
+ */
+function bootstrap_include($theme, $path) {
+  static $included = array();
+  static $themes = array();
+
+  if (!isset($themes[$theme])) {
+    $themes[$theme] = drupal_get_path('theme', $theme);
+  }
+
+  if (!isset($included["$theme:$path"])) {
+    $file = DRUPAL_ROOT . '/' . $themes[$theme] . '/' . $path;
+    if (file_exists($file)) {
+      include_once $file;
+    }
+    else {
+      $file = FALSE;
+    }
+    $included["$theme:$path"] = $file;
+  }
+
+  return $included["$theme:$path"];
+}
+
+/**
+ * Retrieves a setting for the current theme or for a given theme.
+ *
+ * This is a wrapper for theme_get_setting(), ensuring to use deprecated
+ * setting values instead.
+ *
+ * @param string $name
+ *   The name of the setting to be retrieved.
+ * @param string $theme
+ *   The name of a given theme; defaults to the currently active theme.
+ * @param string $prefix
+ *   The prefix used on the $name of the setting, this will be appended with
+ *   "_" automatically if set.
+ * @param mixed $default
+ *   The default value to return if setting doesn't exist or is not set.
+ *
+ * @return mixed
+ *   The value of the requested setting, NULL if the setting does not exist.
+ *
+ * @see theme_get_setting()
+ *
+ * @todo Refactor in 7.x-4.x and get rid of the deprecated settings.
+ */
+function bootstrap_setting($name, $theme = NULL, $prefix = 'bootstrap', $default = NULL) {
+  $prefix = !empty($prefix) ? $prefix . '_' : '';
+  $setting = theme_get_setting($prefix . $name, $theme);
+  switch ($prefix . $name) {
+    case 'bootstrap_cdn_provider':
+      $deprecated = theme_get_setting('bootstrap_cdn', $theme);
+      if (isset($deprecated)) {
+        $setting = empty($deprecated) ? '' : 'jsdelivr';
+      }
+      break;
+
+    case 'bootstrap_cdn_jsdelivr_version':
+      $deprecated = theme_get_setting('bootstrap_cdn', $theme);
+      if (isset($deprecated)) {
+        $setting = empty($deprecated) ? BOOTSTRAP_VERSION : $deprecated;
+      }
+      break;
+
+    case 'bootstrap_cdn_jsdelivr_theme':
+      $deprecated = theme_get_setting('bootstrap_bootswatch', $theme);
+      if (isset($deprecated)) {
+        $setting = empty($deprecated) ? 'bootstrap' : $deprecated;
+      }
+      break;
+
+    case 'bootstrap_forms_smart_descriptions':
+      $deprecated = theme_get_setting('bootstrap_tooltip_descriptions', $theme);
+      if (isset($deprecated)) {
+        $setting = (int) !empty($deprecated);
+      }
+      break;
+
+    case 'bootstrap_forms_smart_descriptions_limit':
+      $deprecated = theme_get_setting('bootstrap_tooltip_descriptions_length', $theme);
+      if (isset($deprecated)) {
+        $setting = (int) !empty($deprecated);
+      }
+      break;
+
+  }
+  return isset($setting) ? $setting : $default;
+}
+
+/**
+ * Sets a theme setting.
+ *
+ * @param string $name
+ *   The name of the setting to set.
+ * @param mixed $value
+ *   The value of the setting to set.
+ * @param string $prefix
+ *   The prefix used on the $name of the setting, this will be appended with
+ *   "_" automatically if set.
+ * @param string $theme
+ *   The name of a given theme; defaults to the currently active theme.
+ */
+function _bootstrap_set_setting($name, $value, $prefix = 'bootstrap', $theme = NULL) {
+  // If no key is given, use the current theme if we can determine it.
+  if (!isset($theme)) {
+    $theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : '';
+  }
+
+  // Trigger at least once so it can populate defaults.
+  theme_get_setting('', $theme);
+
+  // Retrieve the cached settings.
+  $cache = &drupal_static('theme_get_setting', array());
+  $settings = $cache[$theme];
+
+  // Set the value.
+  $prefix = !empty($prefix) ? $prefix . '_' : '';
+  $settings["$prefix$name"] = $value;
+
+  // Set the settings.
+  variable_set('theme_' . $theme . '_settings', $settings);
+}
+
+/**
+ * Retrieves an element's "attributes" array.
+ *
+ * @param array $element
+ *   The individual renderable array element. It is possible to also pass the
+ *   $variables parameter in [pre]process functions and it will logically
+ *   determine the correct path to that particular theme hook's attribute array.
+ *   Passed by reference.
+ * @param string $property
+ *   Determines which attributes array to retrieve. By default, this is the
+ *   normal attributes, but can be "wrapper_attributes" or
+ *   "input_group_attributes".
+ *
+ * @return array
+ *   The attributes array. Passed by reference.
+ */
+function &_bootstrap_get_attributes(array &$element, $property = 'attributes') {
+  // Attempt to retrieve a renderable element attributes first.
+  if (
+    isset($element['#type']) ||
+    isset($element['#theme']) ||
+    isset($element['#pre_render']) ||
+    isset($element['#markup']) ||
+    isset($element['#theme_wrappers']) ||
+    isset($element["#$property"])
+  ) {
+    if (!isset($element["#$property"])) {
+      $element["#$property"] = array();
+    }
+    return $element["#$property"];
+  }
+  // Treat $element as if it were a [pre]process function $variables parameter
+  // and look for a renderable "element".
+  elseif (isset($element['element'])) {
+    if (!isset($element['element']["#$property"])) {
+      $element['element']["#$property"] = array();
+    }
+    return $element['element']["#$property"];
+  }
+
+  // If all else fails, create (if needed) a default "attributes" array. This
+  // will, at the very least, either work or cause an error that can be tracked.
+  if (!isset($element[$property])) {
+    $element[$property] = array();
+  }
+
+  return $element[$property];
+}
+
+/**
+ * Retrieves an element's "class" array.
+ *
+ * @param array $element
+ *   The individual renderable array element. It is possible to also pass the
+ *   $variables parameter in [pre]process functions and it will logically
+ *   determine the correct path to that particular theme hook's classes array.
+ *   Passed by reference.
+ * @param string $property
+ *   Determines which attributes array to retrieve. By default, this is the
+ *   normal attributes, but can be "wrapper_attributes" or
+ *   "input_group_attributes".
+ *
+ * @return array
+ *   The classes array. Passed by reference.
+ */
+function &_bootstrap_get_classes(array &$element, $property = 'attributes') {
+  $attributes = &_bootstrap_get_attributes($element, $property);
+
+  if (!isset($attributes['class'])) {
+    $attributes['class'] = array();
+  }
+  // Contrib modules have a very bad habit of frequently adding classes as
+  // strings, convert them to a proper array.
+  // @see https://www.drupal.org/node/2269653
+  elseif (!is_array($attributes['class'])) {
+    $attributes['class'] = explode(' ', $attributes['class']);
+  }
+
+  // Ensure classes are not duplicated.
+  $attributes['class'] = array_unique($attributes['class']);
+  return $attributes['class'];
+}
+
+/**
+ * Adds a class to an element's render array.
+ *
+ * @param string|array $class
+ *   An individual class or an array of classes to add.
+ * @param array $element
+ *   The individual renderable array element. It is possible to also pass the
+ *   $variables parameter in [pre]process functions and it will logically
+ *   determine the correct path to that particular theme hook's classes array.
+ *   Passed by reference.
+ * @param string $property
+ *   Determines which attributes array to retrieve. By default, this is the
+ *   normal attributes, but can be "wrapper_attributes" or
+ *   "input_group_attributes".
+ */
+function _bootstrap_add_class($class, array &$element, $property = 'attributes') {
+  // Retrieve the element's classes.
+  $classes = &_bootstrap_get_classes($element, $property);
+
+  // Convert the class to an array.
+  if (!is_array($class)) {
+    $class = array($class);
+  }
+
+  // Iterate over all classes to add.
+  foreach ($class as $_class) {
+    // Ensure the class to add does not yet already exist.
+    if (!in_array($_class, $classes)) {
+      $classes[] = $_class;
+    }
+  }
+}
+
+/**
+ * Removes a class from an element's render array.
+ *
+ * @param string|array $class
+ *   An individual class or an array of classes to remove.
+ * @param array $element
+ *   The individual renderable array element. It is possible to also pass the
+ *   $variables parameter in [pre]process functions and it will logically
+ *   determine the correct path to that particular theme hook's classes array.
+ *   Passed by reference.
+ * @param string $property
+ *   Determines which attributes array to retrieve. By default, this is the
+ *   normal attributes, but can be "wrapper_attributes" or
+ *   "input_group_attributes".
+ */
+function _bootstrap_remove_class($class, array &$element, $property = 'attributes') {
+  // Retrieve the element's classes.
+  $classes = &_bootstrap_get_classes($element, $property);
+
+  // Convert the class to an array.
+  if (!is_array($class)) {
+    $class = array($class);
+  }
+
+  // Iterate over all classes to add.
+  foreach ($class as $_class) {
+    $key = array_search($_class, $classes);
+    if ($key !== FALSE) {
+      unset($classes[$key]);
+    }
+  }
+}
+
+/**
+ * Returns a list of base themes for active or provided theme.
+ *
+ * @param string $theme_key
+ *   The machine name of the theme to check, if not set the active theme name
+ *   will be used.
+ * @param bool $include_theme_key
+ *   Whether to append the returned list with $theme_key.
+ *
+ * @return array
+ *   An indexed array of base themes.
+ */
+function _bootstrap_get_base_themes($theme_key = NULL, $include_theme_key = FALSE) {
+  static $themes;
+  if (!isset($theme_key)) {
+    $theme_key = $GLOBALS['theme_key'];
+  }
+  if (!isset($themes[$theme_key])) {
+    $themes[$theme_key] = array_unique(array_filter((array) bootstrap_get_theme_info($theme_key, 'base theme')));
+  }
+  if ($include_theme_key) {
+    $themes[$theme_key][] = $theme_key;
+  }
+  return $themes[$theme_key];
+}
+
+/**
+ * Retrieves the full base/sub-theme ancestry of a theme.
+ *
+ * @param string $theme_key
+ *   The machine name of the theme to check, if not set the active theme name
+ *   will be used.
+ * @param bool $reverse
+ *   Whether or not to return the array of themes in reverse order, where the
+ *   active theme is the first entry.
+ *
+ * @return string[]
+ *   An array of theme names.
+ */
+function _bootstrap_get_ancestry($theme_key = NULL, $reverse = FALSE) {
+  $ancestry = _bootstrap_get_base_themes($theme_key, TRUE);
+  return $reverse ? array_reverse($ancestry) : $ancestry;
+}
+
+/**
+ * Wrapper for the core file_scan_directory() function.
+ *
+ * Finds all files that match a given mask in a given directory and then caches
+ * the results. A general site cache clear will force new scans to be initiated
+ * for already cached directories.
+ *
+ * @param string $dir
+ *   The base directory or URI to scan, without trailing slash.
+ * @param string $mask
+ *   The preg_match() regular expression of the files to find.
+ * @param array $options
+ *   Additional options to pass to file_scan_directory().
+ *
+ * @return array
+ *   An associative array (keyed on the chosen key) of objects with 'uri',
+ *   'filename', and 'name' members corresponding to the matching files.
+ *
+ * @see file_scan_directory()
+ */
+function _bootstrap_file_scan_directory($dir, $mask, array $options = array()) {
+  $files = &drupal_static(__FUNCTION__, array());
+
+  // Generate a unique cache identifier for all parameters passed as a change
+  // in any of them would return different results.
+  $cid = 'theme_registry:bootstrap:files:' . drupal_hash_base64(serialize(func_get_args()));
+
+  // Load from DB cache or scan filesystem if files are not statically cached.
+  if (!isset($files[$cid])) {
+    if (($cache = cache_get($cid)) && isset($cache->data)) {
+      $files[$cid] = $cache->data;
+    }
+    else {
+      $files[$cid] = file_scan_directory($dir, $mask, $options);
+      cache_set($cid, $files[$cid]);
+    }
+  }
+
+  return $files[$cid];
+}
+
+/**
+ * Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities.
+ *
+ * Very similar to core's filter_xss(). It does, however, include the addition
+ * of the "span", "div" and "i" elements which are commonly used in Bootstrap.
+ *
+ * @param string $string
+ *   The string with raw HTML in it. It will be stripped of everything that can
+ *   cause an XSS attack.
+ * @param array $allowed_tags
+ *   An array of allowed tags.
+ *
+ * @return string
+ *   An XSS safe version of $string, or an empty string if $string is not
+ *   valid UTF-8.
+ *
+ * @see filter_xss()
+ * @see filter_xss_admin()
+ *
+ * @deprecated Use filter_xss() or filter_xss_admin() instead.
+ * Will be removed in a future release.
+ */
+function _bootstrap_filter_xss($string, array $allowed_tags = NULL) {
+  if (is_null($allowed_tags)) {
+    $allowed_tags = array(
+      // Inline elements.
+      'a',
+      'cite',
+      'em',
+      'i',
+      'span',
+      'strong',
+
+      // Block elements.
+      'blockquote',
+      'code',
+      'div',
+      'ul',
+      'ol',
+      'li',
+      'dl',
+      'dt',
+      'dd',
+    );
+  }
+  return filter_xss($string, $allowed_tags);
+}
+
+/**
+ * Returns a list of available Bootstrap Glyphicons.
+ *
+ * @param string $version
+ *   The specific version of glyphicons to return. If not set, the latest
+ *   BOOTSTRAP_VERSION will be used.
+ *
+ * @return array
+ *   An associative array of icons keyed by their classes.
+ */
+function _bootstrap_glyphicons($version = NULL) {
+  static $versions;
+  if (!isset($versions)) {
+    $versions = array();
+    $versions['3.0.0'] = array(
+      // Class => Name.
+      'glyphicon-adjust' => 'adjust',
+      'glyphicon-align-center' => 'align-center',
+      'glyphicon-align-justify' => 'align-justify',
+      'glyphicon-align-left' => 'align-left',
+      'glyphicon-align-right' => 'align-right',
+      'glyphicon-arrow-down' => 'arrow-down',
+      'glyphicon-arrow-left' => 'arrow-left',
+      'glyphicon-arrow-right' => 'arrow-right',
+      'glyphicon-arrow-up' => 'arrow-up',
+      'glyphicon-asterisk' => 'asterisk',
+      'glyphicon-backward' => 'backward',
+      'glyphicon-ban-circle' => 'ban-circle',
+      'glyphicon-barcode' => 'barcode',
+      'glyphicon-bell' => 'bell',
+      'glyphicon-bold' => 'bold',
+      'glyphicon-book' => 'book',
+      'glyphicon-bookmark' => 'bookmark',
+      'glyphicon-briefcase' => 'briefcase',
+      'glyphicon-bullhorn' => 'bullhorn',
+      'glyphicon-calendar' => 'calendar',
+      'glyphicon-camera' => 'camera',
+      'glyphicon-certificate' => 'certificate',
+      'glyphicon-check' => 'check',
+      'glyphicon-chevron-down' => 'chevron-down',
+      'glyphicon-chevron-left' => 'chevron-left',
+      'glyphicon-chevron-right' => 'chevron-right',
+      'glyphicon-chevron-up' => 'chevron-up',
+      'glyphicon-circle-arrow-down' => 'circle-arrow-down',
+      'glyphicon-circle-arrow-left' => 'circle-arrow-left',
+      'glyphicon-circle-arrow-right' => 'circle-arrow-right',
+      'glyphicon-circle-arrow-up' => 'circle-arrow-up',
+      'glyphicon-cloud' => 'cloud',
+      'glyphicon-cloud-download' => 'cloud-download',
+      'glyphicon-cloud-upload' => 'cloud-upload',
+      'glyphicon-cog' => 'cog',
+      'glyphicon-collapse-down' => 'collapse-down',
+      'glyphicon-collapse-up' => 'collapse-up',
+      'glyphicon-comment' => 'comment',
+      'glyphicon-compressed' => 'compressed',
+      'glyphicon-copyright-mark' => 'copyright-mark',
+      'glyphicon-credit-card' => 'credit-card',
+      'glyphicon-cutlery' => 'cutlery',
+      'glyphicon-dashboard' => 'dashboard',
+      'glyphicon-download' => 'download',
+      'glyphicon-download-alt' => 'download-alt',
+      'glyphicon-earphone' => 'earphone',
+      'glyphicon-edit' => 'edit',
+      'glyphicon-eject' => 'eject',
+      'glyphicon-envelope' => 'envelope',
+      'glyphicon-euro' => 'euro',
+      'glyphicon-exclamation-sign' => 'exclamation-sign',
+      'glyphicon-expand' => 'expand',
+      'glyphicon-export' => 'export',
+      'glyphicon-eye-close' => 'eye-close',
+      'glyphicon-eye-open' => 'eye-open',
+      'glyphicon-facetime-video' => 'facetime-video',
+      'glyphicon-fast-backward' => 'fast-backward',
+      'glyphicon-fast-forward' => 'fast-forward',
+      'glyphicon-file' => 'file',
+      'glyphicon-film' => 'film',
+      'glyphicon-filter' => 'filter',
+      'glyphicon-fire' => 'fire',
+      'glyphicon-flag' => 'flag',
+      'glyphicon-flash' => 'flash',
+      'glyphicon-floppy-disk' => 'floppy-disk',
+      'glyphicon-floppy-open' => 'floppy-open',
+      'glyphicon-floppy-remove' => 'floppy-remove',
+      'glyphicon-floppy-save' => 'floppy-save',
+      'glyphicon-floppy-saved' => 'floppy-saved',
+      'glyphicon-folder-close' => 'folder-close',
+      'glyphicon-folder-open' => 'folder-open',
+      'glyphicon-font' => 'font',
+      'glyphicon-forward' => 'forward',
+      'glyphicon-fullscreen' => 'fullscreen',
+      'glyphicon-gbp' => 'gbp',
+      'glyphicon-gift' => 'gift',
+      'glyphicon-glass' => 'glass',
+      'glyphicon-globe' => 'globe',
+      'glyphicon-hand-down' => 'hand-down',
+      'glyphicon-hand-left' => 'hand-left',
+      'glyphicon-hand-right' => 'hand-right',
+      'glyphicon-hand-up' => 'hand-up',
+      'glyphicon-hd-video' => 'hd-video',
+      'glyphicon-hdd' => 'hdd',
+      'glyphicon-header' => 'header',
+      'glyphicon-headphones' => 'headphones',
+      'glyphicon-heart' => 'heart',
+      'glyphicon-heart-empty' => 'heart-empty',
+      'glyphicon-home' => 'home',
+      'glyphicon-import' => 'import',
+      'glyphicon-inbox' => 'inbox',
+      'glyphicon-indent-left' => 'indent-left',
+      'glyphicon-indent-right' => 'indent-right',
+      'glyphicon-info-sign' => 'info-sign',
+      'glyphicon-italic' => 'italic',
+      'glyphicon-leaf' => 'leaf',
+      'glyphicon-link' => 'link',
+      'glyphicon-list' => 'list',
+      'glyphicon-list-alt' => 'list-alt',
+      'glyphicon-lock' => 'lock',
+      'glyphicon-log-in' => 'log-in',
+      'glyphicon-log-out' => 'log-out',
+      'glyphicon-magnet' => 'magnet',
+      'glyphicon-map-marker' => 'map-marker',
+      'glyphicon-minus' => 'minus',
+      'glyphicon-minus-sign' => 'minus-sign',
+      'glyphicon-move' => 'move',
+      'glyphicon-music' => 'music',
+      'glyphicon-new-window' => 'new-window',
+      'glyphicon-off' => 'off',
+      'glyphicon-ok' => 'ok',
+      'glyphicon-ok-circle' => 'ok-circle',
+      'glyphicon-ok-sign' => 'ok-sign',
+      'glyphicon-open' => 'open',
+      'glyphicon-paperclip' => 'paperclip',
+      'glyphicon-pause' => 'pause',
+      'glyphicon-pencil' => 'pencil',
+      'glyphicon-phone' => 'phone',
+      'glyphicon-phone-alt' => 'phone-alt',
+      'glyphicon-picture' => 'picture',
+      'glyphicon-plane' => 'plane',
+      'glyphicon-play' => 'play',
+      'glyphicon-play-circle' => 'play-circle',
+      'glyphicon-plus' => 'plus',
+      'glyphicon-plus-sign' => 'plus-sign',
+      'glyphicon-print' => 'print',
+      'glyphicon-pushpin' => 'pushpin',
+      'glyphicon-qrcode' => 'qrcode',
+      'glyphicon-question-sign' => 'question-sign',
+      'glyphicon-random' => 'random',
+      'glyphicon-record' => 'record',
+      'glyphicon-refresh' => 'refresh',
+      'glyphicon-registration-mark' => 'registration-mark',
+      'glyphicon-remove' => 'remove',
+      'glyphicon-remove-circle' => 'remove-circle',
+      'glyphicon-remove-sign' => 'remove-sign',
+      'glyphicon-repeat' => 'repeat',
+      'glyphicon-resize-full' => 'resize-full',
+      'glyphicon-resize-horizontal' => 'resize-horizontal',
+      'glyphicon-resize-small' => 'resize-small',
+      'glyphicon-resize-vertical' => 'resize-vertical',
+      'glyphicon-retweet' => 'retweet',
+      'glyphicon-road' => 'road',
+      'glyphicon-save' => 'save',
+      'glyphicon-saved' => 'saved',
+      'glyphicon-screenshot' => 'screenshot',
+      'glyphicon-sd-video' => 'sd-video',
+      'glyphicon-search' => 'search',
+      'glyphicon-send' => 'send',
+      'glyphicon-share' => 'share',
+      'glyphicon-share-alt' => 'share-alt',
+      'glyphicon-shopping-cart' => 'shopping-cart',
+      'glyphicon-signal' => 'signal',
+      'glyphicon-sort' => 'sort',
+      'glyphicon-sort-by-alphabet' => 'sort-by-alphabet',
+      'glyphicon-sort-by-alphabet-alt' => 'sort-by-alphabet-alt',
+      'glyphicon-sort-by-attributes' => 'sort-by-attributes',
+      'glyphicon-sort-by-attributes-alt' => 'sort-by-attributes-alt',
+      'glyphicon-sort-by-order' => 'sort-by-order',
+      'glyphicon-sort-by-order-alt' => 'sort-by-order-alt',
+      'glyphicon-sound-5-1' => 'sound-5-1',
+      'glyphicon-sound-6-1' => 'sound-6-1',
+      'glyphicon-sound-7-1' => 'sound-7-1',
+      'glyphicon-sound-dolby' => 'sound-dolby',
+      'glyphicon-sound-stereo' => 'sound-stereo',
+      'glyphicon-star' => 'star',
+      'glyphicon-star-empty' => 'star-empty',
+      'glyphicon-stats' => 'stats',
+      'glyphicon-step-backward' => 'step-backward',
+      'glyphicon-step-forward' => 'step-forward',
+      'glyphicon-stop' => 'stop',
+      'glyphicon-subtitles' => 'subtitles',
+      'glyphicon-tag' => 'tag',
+      'glyphicon-tags' => 'tags',
+      'glyphicon-tasks' => 'tasks',
+      'glyphicon-text-height' => 'text-height',
+      'glyphicon-text-width' => 'text-width',
+      'glyphicon-th' => 'th',
+      'glyphicon-th-large' => 'th-large',
+      'glyphicon-th-list' => 'th-list',
+      'glyphicon-thumbs-down' => 'thumbs-down',
+      'glyphicon-thumbs-up' => 'thumbs-up',
+      'glyphicon-time' => 'time',
+      'glyphicon-tint' => 'tint',
+      'glyphicon-tower' => 'tower',
+      'glyphicon-transfer' => 'transfer',
+      'glyphicon-trash' => 'trash',
+      'glyphicon-tree-conifer' => 'tree-conifer',
+      'glyphicon-tree-deciduous' => 'tree-deciduous',
+      'glyphicon-unchecked' => 'unchecked',
+      'glyphicon-upload' => 'upload',
+      'glyphicon-usd' => 'usd',
+      'glyphicon-user' => 'user',
+      'glyphicon-volume-down' => 'volume-down',
+      'glyphicon-volume-off' => 'volume-off',
+      'glyphicon-volume-up' => 'volume-up',
+      'glyphicon-warning-sign' => 'warning-sign',
+      'glyphicon-wrench' => 'wrench',
+      'glyphicon-zoom-in' => 'zoom-in',
+      'glyphicon-zoom-out' => 'zoom-out',
+    );
+    $versions['3.0.1'] = $versions['3.0.0'];
+    $versions['3.0.2'] = $versions['3.0.1'];
+    $versions['3.0.3'] = $versions['3.0.2'];
+    $versions['3.1.0'] = $versions['3.0.3'];
+    $versions['3.1.1'] = $versions['3.1.0'];
+    $versions['3.2.0'] = $versions['3.1.1'];
+    $versions['3.3.0'] = array_merge($versions['3.2.0'], array(
+      'glyphicon-eur' => 'eur',
+    ));
+    $versions['3.3.1'] = $versions['3.3.0'];
+    $versions['3.3.2'] = array_merge($versions['3.3.1'], array(
+      'glyphicon-alert' => 'alert',
+      'glyphicon-apple' => 'apple',
+      'glyphicon-baby-formula' => 'baby-formula',
+      'glyphicon-bed' => 'bed',
+      'glyphicon-bishop' => 'bishop',
+      'glyphicon-bitcoin' => 'bitcoin',
+      'glyphicon-blackboard' => 'blackboard',
+      'glyphicon-cd' => 'cd',
+      'glyphicon-console' => 'console',
+      'glyphicon-copy' => 'copy',
+      'glyphicon-duplicate' => 'duplicate',
+      'glyphicon-education' => 'education',
+      'glyphicon-equalizer' => 'equalizer',
+      'glyphicon-erase' => 'erase',
+      'glyphicon-grain' => 'grain',
+      'glyphicon-hourglass' => 'hourglass',
+      'glyphicon-ice-lolly' => 'ice-lolly',
+      'glyphicon-ice-lolly-tasted' => 'ice-lolly-tasted',
+      'glyphicon-king' => 'king',
+      'glyphicon-knight' => 'knight',
+      'glyphicon-lamp' => 'lamp',
+      'glyphicon-level-up' => 'level-up',
+      'glyphicon-menu-down' => 'menu-down',
+      'glyphicon-menu-hamburger' => 'menu-hamburger',
+      'glyphicon-menu-left' => 'menu-left',
+      'glyphicon-menu-right' => 'menu-right',
+      'glyphicon-menu-up' => 'menu-up',
+      'glyphicon-modal-window' => 'modal-window',
+      'glyphicon-object-align-bottom' => 'object-align-bottom',
+      'glyphicon-object-align-horizontal' => 'object-align-horizontal',
+      'glyphicon-object-align-left' => 'object-align-left',
+      'glyphicon-object-align-right' => 'object-align-right',
+      'glyphicon-object-align-top' => 'object-align-top',
+      'glyphicon-object-align-vertical' => 'object-align-vertical',
+      'glyphicon-oil' => 'oil',
+      'glyphicon-open-file' => 'open-file',
+      'glyphicon-option-horizontal' => 'option-horizontal',
+      'glyphicon-option-vertical' => 'option-vertical',
+      'glyphicon-paste' => 'paste',
+      'glyphicon-pawn' => 'pawn',
+      'glyphicon-piggy-bank' => 'piggy-bank',
+      'glyphicon-queen' => 'queen',
+      'glyphicon-ruble' => 'ruble',
+      'glyphicon-save-file' => 'save-file',
+      'glyphicon-scale' => 'scale',
+      'glyphicon-scissors' => 'scissors',
+      'glyphicon-subscript' => 'subscript',
+      'glyphicon-sunglasses' => 'sunglasses',
+      'glyphicon-superscript' => 'superscript',
+      'glyphicon-tent' => 'tent',
+      'glyphicon-text-background' => 'text-background',
+      'glyphicon-text-color' => 'text-color',
+      'glyphicon-text-size' => 'text-size',
+      'glyphicon-triangle-bottom' => 'triangle-bottom',
+      'glyphicon-triangle-left' => 'triangle-left',
+      'glyphicon-triangle-right' => 'triangle-right',
+      'glyphicon-triangle-top' => 'triangle-top',
+      'glyphicon-yen' => 'yen',
+    ));
+    $versions['3.3.4'] = array_merge($versions['3.3.2'], array(
+      'glyphicon-btc' => 'btc',
+      'glyphicon-jpy' => 'jpy',
+      'glyphicon-rub' => 'rub',
+      'glyphicon-xbt' => 'xbt',
+    ));
+    $versions['3.3.5'] = $versions['3.3.4'];
+    $versions['3.3.6'] = $versions['3.3.5'];
+    $versions['3.3.7'] = $versions['3.3.6'];
+    $versions['3.4.0'] = $versions['3.3.7'];
+    $versions['3.4.1'] = $versions['3.4.0'];
+  }
+
+  // Return a specific versions icon set.
+  if (isset($version) && isset($versions[$version])) {
+    return $versions[$version];
+  }
+
+  // Return the latest version.
+  return $versions[BOOTSTRAP_VERSION];
+}
+
+/**
+ * Returns a specific Bootstrap Glyphicon as rendered HTML markup.
+ *
+ * @param string $name
+ *   The icon name, minus the "glyphicon-" prefix.
+ * @param string $default
+ *   (Optional) The default value to return.
+ * @param array $attributes
+ *   (Optional) Additional attributes to merge onto the icon.
+ *
+ * @return string
+ *   The HTML markup containing the icon defined by $name, $default value if
+ *   icon does not exist or returns empty output for whatever reason.
+ */
+function _bootstrap_icon($name, $default = NULL, array $attributes = array()) {
+  $icon = _bootstrap_glyphicon($name, $default, $attributes);
+  return render($icon);
+}
+
+/**
+ * Returns a specific Bootstrap Glyphicon as a render array.
+ *
+ * Note: This function was added to keep BC with the former _bootstrap_icon()
+ * implementation since it didn't return a render array. It is basically a
+ * backport of 8.x-3.x code so the added $attributes parameter can be more
+ * easily dealt with.
+ *
+ * @param string $name
+ *   The icon name, minus the "glyphicon-" prefix.
+ * @param array|string $default
+ *   (Optional) The default render array to use if $name is not available.
+ * @param array $attributes
+ *   (Optional) Additional attributes to merge onto the icon.
+ *
+ * @see https://www.drupal.org/project/bootstrap/issues/2844885
+ *
+ * @return array
+ *   The render containing the icon defined by $name, $default value if
+ *   icon does not exist or returns NULL if no icon could be rendered.
+ */
+function _bootstrap_glyphicon($name, $default = array(), array $attributes = array()) {
+  $icon = array();
+
+  // Ensure the icon specified is a valid Bootstrap Glyphicon.
+  if (_bootstrap_glyphicons_supported() && in_array($name, _bootstrap_glyphicons())) {
+    // Attempt to use the Icon API module, if enabled and it generates output.
+    if (module_exists('icon')) {
+      $icon = array(
+        '#theme' => 'icon',
+        '#bundle' => 'bootstrap',
+        '#icon' => 'glyphicon-' . $name,
+        '#attributes' => $attributes,
+      );
+    }
+    else {
+      $icon = array(
+        '#theme' => 'html_tag',
+        '#tag' => 'span',
+        '#value' => '',
+        '#attributes' => $attributes,
+      );
+
+      // Unlike 8.x-3.x, it will be easier to add the classes and aria-hidden
+      // attribute afterwards since there is a passed default $attributes
+      // parameter and drupal_array_merge_deep() is notorious for not properly
+      // merging attributes, especially when dealing with classes.
+      _bootstrap_add_class(array('icon', 'glyphicon', 'glyphicon-' . $name), $icon);
+      $icon['#attributes']['aria-hidden'] = 'true';
+    }
+  }
+
+  // Return the icon.
+  if (!empty($icon)) {
+    return $icon;
+  }
+
+  // _bootstrap_icon() may pass NULL as $default. If so, return an empty array.
+  return isset($default) ? $default : array();
+}
+
+/**
+ * Determine whether or not Bootstrap Glyphicons can be used.
+ */
+function _bootstrap_glyphicons_supported() {
+  global $theme;
+
+  // Use the advanced drupal_static() pattern, since this has the potential to
+  // be called very often by _bootstrap_icon().
+  static $drupal_static_fast;
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['supported'] = &drupal_static(__FUNCTION__);
+  }
+
+  // Get static data.
+  $supported = &$drupal_static_fast['supported'];
+
+  // Retrieve supported themes.
+  if (!isset($supported)) {
+    $supported = array();
+
+    // Retrieve cached data.
+    $cid = 'theme_registry:bootstrap:icon_support';
+    if (($cache = cache_get($cid)) && !empty($cache->data)) {
+      $supported = $cache->data;
+    }
+  }
+
+  // Determine active theme support if not yet set.
+  if (!isset($supported[$theme])) {
+    // Bootstrap based themes are enabled by default to use CDN. Check if
+    // that is the case here so no file discovery is necessary. If the active
+    // theme does not have this setting, it falls back to the base theme that
+    // does.
+    $supported[$theme] = !!bootstrap_get_cdn_assets('css', NULL, $theme);
+
+    // CDN not used, iterate over all of the active (base) themes to determine
+    // if they contain glyphicon font files.
+    if (!$supported[$theme]) {
+      foreach (_bootstrap_get_base_themes($theme, TRUE) as $_theme) {
+        // Scan the theme for files.
+        $fonts = _bootstrap_file_scan_directory(drupal_get_path('theme', $_theme), '/glyphicons-halflings-regular\.(eot|svg|ttf|woff)$/');
+
+        // Fonts found, stop the search.
+        if (!empty($fonts)) {
+          $supported[$theme] = TRUE;
+          break;
+        }
+      }
+    }
+
+    // Cache all supported themes now that this theme is added to the array.
+    cache_set($cid, $supported);
+  }
+
+  return $supported[$theme];
+}
+
+/**
+ * Determine whether a specific element is a button.
+ *
+ * @param array $element
+ *   A renderable element.
+ *
+ * @return bool
+ *   TRUE or FALSE.
+ */
+function _bootstrap_is_button(array $element) {
+  return
+    !empty($element['#type']) &&
+    !empty($element['#value']) && (
+      $element['#type'] === 'button' ||
+      $element['#type'] === 'submit' ||
+      $element['#type'] === 'image_button'
+    );
+}
+
+/**
+ * Adds a specific Bootstrap class to color a button based on its text value.
+ *
+ * @param array $element
+ *   The form element, passed by reference.
+ */
+function _bootstrap_colorize_button(array &$element) {
+  if (_bootstrap_is_button($element)) {
+    // Do not add the class if one is already present in the array.
+    $button_classes = array(
+      'btn-default',
+      'btn-primary',
+      'btn-success',
+      'btn-info',
+      'btn-warning',
+      'btn-danger',
+      'btn-link',
+    );
+    $class_intersection = array_intersect($button_classes, $element['#attributes']['class']);
+    if (empty($class_intersection)) {
+      // Get the matched class.
+      $class = bootstrap_setting('button_colorize') ? _bootstrap_colorize_text($element['#value']) : FALSE;
+      // If no particular class matched, use the default style.
+      if (!$class) {
+        $class = 'default';
+      }
+      $element['#attributes']['class'][] = 'btn-' . $class;
+    }
+  }
+}
+
+/**
+ * Matches a Bootstrap class based on a string value.
+ *
+ * @param string $string
+ *   The string to match classes against.
+ * @param string $default
+ *   The default class to return if no match is found.
+ *
+ * @return string
+ *   The Bootstrap class matched against the value of $haystack or $default if
+ *   no match could be made.
+ */
+function _bootstrap_colorize_text($string, $default = '') {
+  static $texts;
+  if (!isset($texts)) {
+    $texts = array(
+      // Text that match these specific strings are checked first.
+      'matches' => array(
+        // Primary class.
+        t('Download feature')   => 'primary',
+
+        // Success class.
+        t('Add effect')         => 'success',
+        t('Add and configure')  => 'success',
+
+        // Info class.
+        t('Save and add')       => 'info',
+        t('Add another item')   => 'info',
+        t('Update style')       => 'info',
+      ),
+
+      // Text that contain these words anywhere in the string are checked last.
+      'contains' => array(
+        // Primary class.
+        t('Confirm')            => 'primary',
+        t('Filter')             => 'primary',
+        t('Log in')             => 'primary',
+        t('Submit')             => 'primary',
+        t('Search')             => 'primary',
+        t('Upload')             => 'primary',
+
+        // Success class.
+        t('Add')                => 'success',
+        t('Create')             => 'success',
+        t('Save')               => 'success',
+        t('Write')              => 'success',
+
+        // Warning class.
+        t('Export')             => 'warning',
+        t('Import')             => 'warning',
+        t('Restore')            => 'warning',
+        t('Rebuild')            => 'warning',
+
+        // Info class.
+        t('Apply')              => 'info',
+        t('Update')             => 'info',
+
+        // Danger class.
+        t('Delete')             => 'danger',
+        t('Remove')             => 'danger',
+      ),
+    );
+
+    // Allow sub-themes to alter this array of patterns.
+    drupal_alter('bootstrap_colorize_text', $texts);
+  }
+
+  // Iterate over the array.
+  foreach ($texts as $pattern => $strings) {
+    foreach ($strings as $value => $class) {
+      switch ($pattern) {
+        case 'matches':
+          if ($string === $value) {
+            return $class;
+          }
+          break;
+
+        case 'contains':
+          if (strpos(drupal_strtolower($string), drupal_strtolower($value)) !== FALSE) {
+            return $class;
+          }
+          break;
+      }
+    }
+  }
+
+  // Return the default if nothing was matched.
+  return $default;
+}
+
+/**
+ * Adds an icon to button element based on its text value.
+ *
+ * @param array $element
+ *   The form element, passed by reference.
+ */
+function _bootstrap_iconize_button(array &$element) {
+  if (bootstrap_setting('button_iconize') && _bootstrap_is_button($element) && ($icon = _bootstrap_iconize_text($element['#value']))) {
+    $element['#icon'] = $icon;
+  }
+}
+
+/**
+ * Matches a Bootstrap Glyphicon based on a string value.
+ *
+ * @param string $string
+ *   The string to match classes against.
+ * @param string $default
+ *   The default icon to return if no match is found.
+ *
+ * @return string
+ *   The Bootstrap icon matched against the value of $haystack or $default if
+ *   no match could be made.
+ */
+function _bootstrap_iconize_text($string, $default = '') {
+  static $texts;
+  if (!isset($texts)) {
+    $texts = array(
+      // Text that match these specific strings are checked first.
+      'matches' => array(),
+
+      // Text that contain these words anywhere in the string are checked last.
+      'contains' => array(
+        t('Manage')     => 'cog',
+        t('Configure')  => 'cog',
+        t('Download')   => 'download',
+        t('Export')     => 'export',
+        t('Filter')     => 'filter',
+        t('Import')     => 'import',
+        t('Save')       => 'ok',
+        t('Update')     => 'ok',
+        t('Edit')       => 'pencil',
+        t('Add')        => 'plus',
+        t('Write')      => 'plus',
+        t('Cancel')     => 'remove',
+        t('Delete')     => 'trash',
+        t('Remove')     => 'trash',
+        t('Upload')     => 'upload',
+        t('Log In')     => 'log-in',
+      ),
+    );
+
+    // Allow sub-themes to alter this array of patterns.
+    drupal_alter('bootstrap_iconize_text', $texts);
+  }
+
+  // Iterate over the array.
+  foreach ($texts as $pattern => $strings) {
+    foreach ($strings as $value => $icon) {
+      switch ($pattern) {
+        case 'matches':
+          if ($string === $value) {
+            return _bootstrap_icon($icon, $default);
+          }
+          break;
+
+        case 'contains':
+          if (strpos(drupal_strtolower($string), drupal_strtolower($value)) !== FALSE) {
+            return _bootstrap_icon($icon, $default);
+          }
+          break;
+      }
+    }
+  }
+
+  // Return a default icon if nothing was matched.
+  return _bootstrap_icon($default);
+}
+
+/**
+ * Invokes a specific suggestion's preprocess functions.
+ *
+ * @param array $variables
+ *   The theme implementation variables array.
+ */
+function _bootstrap_preprocess_theme_suggestion(array &$variables) {
+  $registry = theme_get_registry();
+  if (!empty($variables['theme_hook_suggestion']) && !empty($registry[$variables['theme_hook_suggestion']]['preprocess functions'])) {
+    // Save the suggestion as the hook to pass to the function.
+    $hook = $variables['theme_hook_suggestion'];
+
+    // Iterate over the preprocess functions.
+    foreach ($registry[$hook]['preprocess functions'] as $function) {
+      // Ensure that the function is not this one (recursive) and exists.
+      if ($function !== __FUNCTION__ && function_exists($function)) {
+        // Invoke theme hook suggestion preprocess function.
+        $function($variables, $hook);
+
+        // Unset the theme_hook_suggestion so the suggestion's preprocess
+        // functions can provide theme_hook_suggestions if needed.
+        if (!empty($variables['theme_hook_suggestions'])) {
+          unset($variables['theme_hook_suggestion']);
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Invokes a specific suggestion's process functions.
+ *
+ * @param array $variables
+ *   The theme implementation variables array.
+ */
+function _bootstrap_process_theme_suggestion(array &$variables) {
+  $registry = theme_get_registry();
+  if (!empty($variables['theme_hook_suggestion']) && !empty($registry[$variables['theme_hook_suggestion']]['process functions'])) {
+    // Save the suggestion as the hook to pass to the function.
+    $hook = $variables['theme_hook_suggestion'];
+
+    // Iterate over the process functions.
+    foreach ($registry[$hook]['process functions'] as $function) {
+      if (function_exists($function)) {
+        // Invoke theme hook suggestion process function.
+        $function($variables, $hook);
+
+        // Unset the theme_hook_suggestion so the suggestion's preprocess
+        // functions can provide theme_hook_suggestions if needed.
+        if (!empty($variables['theme_hook_suggestions'])) {
+          unset($variables['theme_hook_suggestion']);
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Determines if a string of text is considered "simple".
+ *
+ * @param string $string
+ *   The string of text to check "simple" criteria on.
+ * @param int|false $length
+ *   The length of characters used to determine whether or not $string is
+ *   considered "simple". Set explicitly to FALSE to disable this criteria.
+ * @param array|false $allowed_tags
+ *   An array of allowed tag elements. Set explicitly to FALSE to disable this
+ *   criteria.
+ * @param bool $html
+ *   A variable, passed by reference, that indicates whether or not the
+ *   string contains HTML.
+ *
+ * @return bool
+ *   Returns TRUE if the $string is considered "simple", FALSE otherwise.
+ */
+function _bootstrap_is_simple_string($string, $length = 250, $allowed_tags = NULL, &$html = FALSE) {
+  // Use the advanced drupal_static() pattern, since this is called very often.
+  static $drupal_static_fast;
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['strings'] = &drupal_static(__FUNCTION__);
+  }
+  $strings = &$drupal_static_fast['strings'];
+  if (!isset($strings[$string])) {
+    $plain_string = strip_tags($string);
+    $simple = TRUE;
+    if ($allowed_tags !== FALSE) {
+      $filtered_string = filter_xss($string, $allowed_tags);
+      $html = $filtered_string !== $plain_string;
+      $simple = $simple && $string === $filtered_string;
+    }
+    if ($length !== FALSE) {
+      $simple = $simple && strlen($plain_string) <= intval($length);
+    }
+    $strings[$string] = $simple;
+  }
+  return $strings[$string];
+}
+
+/**
+ * Determines if the Path Breadcrumbs module theme function should be used.
+ *
+ * @param string $theme
+ *   The machine name of a specific theme to determine status if the Path
+ *   Breadcrumbs module has been configured to only use its internal function
+ *   on a specific list of themes.
+ *
+ * @return bool
+ *   TRUE or FALSE
+ */
+function _bootstrap_use_path_breadcrumbs($theme = NULL) {
+  static $path_breadcrumbs;
+
+  if (!isset($path_breadcrumbs)) {
+    $path_breadcrumbs = FALSE;
+
+    // Use active theme as the theme key if not explicitly set.
+    if (!isset($theme)) {
+      $theme = $GLOBALS['theme_key'];
+    }
+
+    // Determine whether or not the internal Path Breadcrumbs theme function
+    // should be used or not.
+    if (function_exists('path_breadcrumbs_breadcrumb') && module_exists('path_breadcrumbs')) {
+      $internal_render = variable_get('path_breadcrumbs_internal_render', 1);
+      $themes = variable_get('path_breadcrumbs_internal_render_themes', array());
+      $path_breadcrumbs = ($internal_render && (empty($themes) || in_array($theme, $themes)));
+    }
+  }
+
+  return $path_breadcrumbs;
+}
+
+/**
+ * @} End of "ingroup utility".
+ */

+ 104 - 0
mydata/themes/bootstrap/includes/deprecated.inc

@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * @file
+ * deprecated.inc
+ *
+ * This contains all the currently deprecated functions that will be removed
+ * in the next minor or major release.
+ */
+
+/**
+ * Pre-render input elements.
+ *
+ * @deprecated Use proper hooks instead. Will be removed in 7.x-3.2.
+ *
+ * @see hook_pre_render()
+ *
+ * @todo Remove in 7.x-3.2.
+ */
+function _bootstrap_pre_render_input($element) {
+  return bootstrap_pre_render($element);
+}
+
+/**
+ * Pre-render fieldset element.
+ *
+ * @deprecated Use proper hooks instead. Will be removed in 7.x-3.2.
+ *
+ * @see hook_pre_render_HOOK()
+ *
+ * @todo Remove in 7.x-3.2.
+ */
+function _bootstrap_pre_render_fieldset($element) {
+  return bootstrap_pre_render_fieldset($element);
+}
+
+/**
+ * Internal function used to process all elements.
+ *
+ * @deprecated Use proper hooks instead. Will be removed in 7.x-3.2.
+ *
+ * @see hook_form_process()
+ *
+ * @todo Remove in 7.x-3.2.
+ */
+function _bootstrap_process_element($element, &$form_state, &$form) {
+  $element = bootstrap_form_process($element, $form_state, $form);
+
+  // Process form actions.
+  if (!empty($element['#type']) && $element['#type'] === 'actions') {
+    $element = bootstrap_form_process_actions($element, $form_state, $form);
+  }
+
+  // Process text_format elements.
+  if (isset($element['#type']) && $element['#type'] === 'text_format') {
+    $element = bootstrap_form_process_text_format($element, $form_state, $form);
+  }
+
+  return $element;
+}
+
+/**
+ * Internal function used to process the fieldset element.
+ *
+ * @deprecated Use proper hooks instead. Will be removed in 7.x-3.2.
+ *
+ * @see hook_form_process_HOOK()
+ *
+ * @todo Remove in 7.x-3.2.
+ */
+function _bootstrap_process_fieldset($element, &$form_state, &$form) {
+  // Purposefully left empty, there's nothing to process (just pre-render now).
+}
+
+/**
+ * Helper function for determining if a tooltip can be used for a description.
+ *
+ * @param string $description
+ *   The string of text to process.
+ *
+ * @deprecated Will be removed in 7.x-3.2.
+ *
+ * @see _bootstrap_simple_string()
+ * @see bootstrap_element_smart_description()
+ *
+ * @todo Remove in 7.x-3.2.
+ */
+function _bootstrap_tooltip_description($description) {
+  // Determine if tooltips are enabled.
+  static $enabled;
+  if (!isset($enabled)) {
+    $enabled = bootstrap_setting('tooltip_enabled') && bootstrap_setting('forms_smart_descriptions');
+  }
+  // Immediately return if "simple" tooltip descriptions are not enabled.
+  if (!$enabled) {
+    return FALSE;
+  }
+  $allowed_tags = array('b', 'code', 'em', 'i', 'kbd', 'span', 'strong');
+  $length = (int) bootstrap_setting('forms_smart_descriptions_length');
+  if (empty($length)) {
+    $length = FALSE;
+  }
+  return _bootstrap_is_simple_string($description, $length, $allowed_tags);
+}

+ 40 - 0
mydata/themes/bootstrap/includes/icons.inc

@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Provide Bootstrap Glyphicons support via the Icon API module.
+ */
+
+require_once dirname(__FILE__) . '/common.inc';
+
+/**
+ * Implements hook_icon_providers().
+ */
+function bootstrap_icon_providers() {
+  $providers['bootstrap'] = array(
+    'title' => t('Bootstrap'),
+    'url' => 'https://getbootstrap.com/docs/3.3/components/#glyphicons',
+  );
+  return $providers;
+}
+
+/**
+ * Implements hook_icon_bundles().
+ */
+function bootstrap_icon_bundles() {
+  $bundles['bootstrap'] = array(
+    'render' => 'sprite',
+    'provider' => 'bootstrap',
+    'title' => t('Bootstrap'),
+    'version' => t('Icons by Glyphicons'),
+    'variations' => array(
+      'icon-white' => t('White'),
+    ),
+    'settings' => array(
+      'tag' => 'span',
+    ),
+    'icons' => _bootstrap_glyphicons(),
+  );
+
+  return $bundles;
+}

+ 134 - 0
mydata/themes/bootstrap/includes/pre-render.inc

@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * @file
+ * pre-render.inc
+ *
+ * Contains various implementations for #pre_render callbacks on elements.
+ */
+
+/**
+ * Implements hook_pre_render().
+ */
+function bootstrap_pre_render($element) {
+  if (!empty($element['#bootstrap_ignore_pre_render'])) {
+    return $element;
+  }
+
+  // Only add the "form-control" class to supported theme hooks.
+  $theme_hooks = array(
+    'password',
+    'select',
+    'textarea',
+    'textfield',
+  );
+
+  // Additionally, support some popular 3rd-party modules that don't follow
+  // standards by creating custom theme hooks to use in their element types.
+  // Go ahead and merge in the theme hooks as a start since most elements mimic
+  // their theme hook counterparts as well.
+  $types = array_merge($theme_hooks, array(
+    // Elements module (HTML5).
+    'date',
+    'datefield',
+    'email',
+    'emailfield',
+    'number',
+    'numberfield',
+    'range',
+    'rangefield',
+    'search',
+    'searchfield',
+    'tel',
+    'telfield',
+    'url',
+    'urlfield',
+
+    // Webform module.
+    'webform_email',
+    'webform_number',
+  ));
+
+  // Determine element theme hook.
+  $theme = !empty($element['#theme']) ? $element['#theme'] : FALSE;
+
+  // Handle array of theme hooks, just use first one (rare, but could happen).
+  if (is_array($theme)) {
+    $theme = array_shift($theme);
+  }
+
+  // Remove any suggestions.
+  $parts = explode('__', $theme);
+  $theme = array_shift($parts);
+
+  // Determine element type.
+  $type = !empty($element['#type']) ? $element['#type'] : FALSE;
+
+  // Add necessary classes for specific element types/theme hooks.
+  if (($theme && in_array($theme, $theme_hooks)) || ($type && in_array($type, $types)) || ($type === 'file' && empty($element['#managed_file']))) {
+    $element['#attributes']['class'][] = 'form-control';
+  }
+  if ($type === 'machine_name') {
+    $element['#wrapper_attributes']['class'][] = 'form-inline';
+  }
+
+  // Add smart descriptions to the element, if necessary.
+  bootstrap_element_smart_description($element);
+
+  // Return the modified element.
+  return $element;
+}
+
+/**
+ * Implements hook_pre_render_HOOK().
+ */
+function bootstrap_pre_render_fieldset($element) {
+  // Fieldsets may be rendered outside of a Form API context.
+  if (!empty($element['#bootstrap_ignore_pre_render']) || !isset($element['#parents']) || !isset($element['#groups'])) {
+    return $element;
+  }
+  // Inject group member elements belonging to this group.
+  $parents = implode('][', $element['#parents']);
+  $children = element_children($element['#groups'][$parents]);
+  if (!empty($children)) {
+    if (empty($element['#default_tab'])) {
+      $children_keys = array_values($children);
+      $element['#default_tab'] = $element['#groups'][$parents][array_shift($children_keys)]['#id'];
+    }
+    foreach ($children as $key) {
+      // Break references and indicate that the element should be rendered as
+      // group member.
+      $child = (array) $element['#groups'][$parents][$key];
+      $child['#attributes']['id'] = $child['#id'];
+      $child['#group_fieldset'] = TRUE;
+      // Inject the element as new child element.
+      $element[] = $child;
+
+      $sort = TRUE;
+    }
+    // Re-sort the element's children if we injected group member elements.
+    if (isset($sort)) {
+      $element['#sorted'] = FALSE;
+    }
+  }
+
+  if (isset($element['#group'])) {
+    $group = $element['#group'];
+    // If this element belongs to a group, but the group-holding element does
+    // not exist, we need to render it (at its original location).
+    if (!isset($element['#groups'][$group]['#group_exists'])) {
+      // Intentionally empty to clarify the flow; we simply return $element.
+    }
+    // If we injected this element into the group, then we want to render it.
+    elseif (!empty($element['#group_fieldset'])) {
+      // Intentionally empty to clarify the flow; we simply return $element.
+    }
+    // Otherwise, this element belongs to a group and the group exists, so we do
+    // not render it.
+    elseif (element_children($element['#groups'][$group])) {
+      $element['#printed'] = TRUE;
+    }
+  }
+
+  return $element;
+}

+ 110 - 0
mydata/themes/bootstrap/includes/process.inc

@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * @file
+ * process.inc
+ *
+ * Contains various implementations for #process callbacks on elements.
+ */
+
+/**
+ * Implements hook_form_process().
+ */
+function bootstrap_form_process($element, &$form_state, &$form) {
+  if (!empty($element['#bootstrap_ignore_process'])) {
+    return $element;
+  }
+
+  if (!empty($element['#attributes']['class']) && is_array($element['#attributes']['class'])) {
+    $key = array_search('container-inline', $element['#attributes']['class']);
+    if ($key !== FALSE) {
+      $element['#attributes']['class'][$key] = 'form-inline';
+    }
+
+    if (in_array('form-wrapper', $element['#attributes']['class'])) {
+      $element['#attributes']['class'][] = 'form-group';
+    }
+  }
+
+  // Automatically inject the nearest button found after this element if
+  // #input_group_button exists.
+  if (!empty($element['#input_group_button'])) {
+    // Obtain the parent array to limit search.
+    $array_parents = array();
+    if (!empty($element['#array_parents'])) {
+      $array_parents += $element['#array_parents'];
+      // Remove the current element from the array.
+      array_pop($array_parents);
+    }
+
+    // If element is nested, return the referenced parent from the form.
+    if (!empty($array_parents)) {
+      $parent = &drupal_array_get_nested_value($form, $array_parents);
+    }
+    // Otherwise return the complete form.
+    else {
+      $parent = &$form;
+    }
+
+    // Ignore buttons before we find the element in the form.
+    $found_current_element = FALSE;
+    foreach (element_children($parent, TRUE) as $child) {
+      if ($parent[$child] === $element) {
+        $found_current_element = TRUE;
+        continue;
+      }
+
+      if ($found_current_element && _bootstrap_is_button($parent[$child]) && (!isset($parent[$child]['#access']) || !!$parent[$child]['#access'])) {
+        $element['#field_suffix'] = drupal_render($parent[$child]);
+        break;
+      }
+    }
+  }
+
+  return $element;
+}
+
+/**
+ * Implements hook_form_process_HOOK().
+ */
+function bootstrap_form_process_actions($element, &$form_state, &$form) {
+  $element['#attributes']['class'][] = 'form-actions';
+
+  if (!empty($element['#bootstrap_ignore_process'])) {
+    return $element;
+  }
+
+  foreach (element_children($element) as $child) {
+    _bootstrap_iconize_button($element[$child]);
+  }
+  return $element;
+}
+
+/**
+ * Implements hook_form_process_HOOK().
+ */
+function bootstrap_form_process_text_format($element, &$form_state, &$form) {
+  if (!empty($element['#bootstrap_ignore_process'])) {
+    return $element;
+  }
+
+  // Provide smart description on the value text area.
+  bootstrap_element_smart_description($element, $element['value']);
+
+  // Allow the elements inside to be displayed inline.
+  $element['format']['#attributes']['class'][] = 'form-inline';
+
+  // Remove the cluttering guidelines; they can be viewed on a separate page.
+  $element['format']['guidelines']['#access'] = FALSE;
+
+  // Hide the select label.
+  $element['format']['format']['#title_display'] = 'none';
+
+  // Make the select element smaller using a Bootstrap class.
+  $element['format']['format']['#attributes']['class'][] = 'input-sm';
+
+  // Support the Bootstrap Select plugin if it is used.
+  $element['format']['format']['#attributes']['data-style'] = 'btn-sm btn-default';
+
+  return $element;
+}

+ 509 - 0
mydata/themes/bootstrap/includes/registry.inc

@@ -0,0 +1,509 @@
+<?php
+
+/**
+ * @file
+ * List of functions used to alter the theme registry in Bootstrap based themes.
+ */
+
+/**
+ * @addtogroup registry
+ * @{
+ */
+
+// Define additional sub-groups for creating lists for all the theme files.
+/**
+ * @defgroup theme_functions Theme Functions (.func.php)
+ *
+ * List of theme functions used in the Drupal Bootstrap base theme.
+ *
+ * View the parent topic for additional documentation.
+ */
+/**
+ * @defgroup theme_preprocess Theme Preprocess Functions (.vars.php)
+ *
+ * List of theme preprocess functions used in the Drupal Bootstrap base theme.
+ *
+ * View the parent topic for additional documentation.
+ */
+/**
+ * @defgroup theme_process Theme Process Functions (.vars.php)
+ *
+ * List of theme process functions used in the Drupal Bootstrap base theme.
+ *
+ * View the parent topic for additional documentation.
+ */
+/**
+ * @defgroup templates Theme Templates (.tpl.php)
+ *
+ * List of theme templates used in the Drupal Bootstrap base theme.
+ *
+ * View the parent topic for additional documentation.
+ */
+
+/**
+ * Stub implementation for bootstrap_theme().
+ *
+ * This base-theme's custom theme hook implementations. Never define "path"
+ * or "template" as these are detected and automatically added.
+ *
+ * @see bootstrap_theme_registry_alter()
+ * @see bootstrap_theme()
+ * @see hook_theme()
+ */
+function _bootstrap_theme(&$existing, $type, $theme, $path) {
+  // Bootstrap Carousels.
+  $hooks['bootstrap_carousel'] = array(
+    'variables' => array(
+      'attributes' => array(),
+      'items' => array(),
+      'start_index' => 0,
+      'controls' => TRUE,
+      'indicators' => TRUE,
+      'interval' => 5000,
+      'pause' => 'hover',
+      'wrap' => TRUE,
+    ),
+  );
+
+  // Bootstrap Dropdowns.
+  $hooks['bootstrap_dropdown'] = array(
+    'render element' => 'element',
+  );
+
+  // Bootstrap Modals.
+  $hooks['bootstrap_modal'] = array(
+    'variables' => array(
+      'heading' => '',
+      'body' => '',
+      'footer' => '',
+      'dialog_attributes' => array(),
+      'attributes' => array(),
+      'size' => '',
+      'html_heading' => FALSE,
+    ),
+  );
+
+  // Bootstrap Panels.
+  $hooks['bootstrap_panel'] = array(
+    'render element' => 'element',
+  );
+
+  // Bootstrap search form wrapper.
+  // @todo Remove this as it's not really needed and should use suggestions.
+  $hooks['bootstrap_search_form_wrapper'] = array(
+    'render element' => 'element',
+  );
+  return $hooks;
+}
+
+/**
+ * Implements hook_theme_registry_alter().
+ */
+function bootstrap_theme_registry_alter(&$registry) {
+  // Retrieve the active theme names.
+  $themes = _bootstrap_get_base_themes(NULL, TRUE);
+
+  // Return the theme registry unaltered if it is not Bootstrap based.
+  if (!in_array('bootstrap', $themes)) {
+    return;
+  }
+
+  // Inject the "footer" variable default in the existing "table" hook.
+  // @see https://www.drupal.org/node/806982
+  // @todo Make this discoverable in some way instead of a manual injection.
+  $registry['table']['variables']['footer'] = NULL;
+
+  // Process registered hooks in the theme registry.
+  _bootstrap_process_theme_registry($registry, $themes);
+
+  // Process registered hooks in the theme registry to add necessary theme hook
+  // suggestion phased function invocations. This must be run after separately
+  // and after all includes have been loaded.
+  _bootstrap_process_theme_registry_suggestions($registry, $themes);
+
+  // Merge both "html" and "page" theme hooks into "maintenance_page". Create
+  // a fake "page" variable to satisfy both "html" and "page" preprocess/process
+  // functions. Whether or not they stumble over each other doesn't matter since
+  // the "maintenance_page" theme hook uses the "content" variable instead.
+  $registry['maintenance_page']['variables']['page'] = array(
+    '#show_messages' => TRUE,
+    '#children' => NULL,
+    'page_bottom' => array(),
+    'page_top' => array(),
+  );
+  foreach (array('html', 'page') as $theme_hook) {
+    foreach (array('includes', 'preprocess functions', 'process functions') as $property) {
+      if (!isset($registry['maintenance_page'][$property])) {
+        $registry['maintenance_page'][$property] = array();
+      }
+      if (!isset($registry[$theme_hook][$property])) {
+        $registry[$theme_hook][$property] = array();
+      }
+      $registry['maintenance_page'][$property] = array_merge($registry['maintenance_page'][$property], $registry[$theme_hook][$property]);
+    }
+  }
+
+  // Post-process theme registry. This happens after all altering has occurred.
+  foreach ($registry as $hook => $info) {
+    // Ensure uniqueness.
+    if (!empty($registry[$hook]['includes'])) {
+      $registry[$hook]['includes'] = array_unique($info['includes']);
+    }
+    if (!empty($registry[$hook]['preprocess functions'])) {
+      $registry[$hook]['preprocess functions'] = array_unique($info['preprocess functions']);
+    }
+    if (!empty($registry[$hook]['process functions'])) {
+      $registry[$hook]['process functions'] = array_unique($info['process functions']);
+    }
+
+    // Ensure "theme path" is set.
+    if (!isset($registry[$hook]['theme path'])) {
+      $registry[$hook]['theme path'] = $GLOBALS['theme_path'];
+    }
+  }
+}
+
+/**
+ * Processes registered hooks in the theme registry against list of themes.
+ *
+ * Discovers and fills missing elements in the theme registry. This is similar
+ * to _theme_process_registry(), however severely modified for Bootstrap based
+ * themes.
+ *
+ * All additions or modifications must live in `./templates`, relative to the
+ * base theme or sub-theme's base folder. These files can be organized in any
+ * order using sub-folders as it searches recursively.
+ *
+ * Adds or modifies the following theme hook keys:
+ *  - `includes`: When a variables file `*.vars.php` is found.
+ *  - `includes`: When a function file `*.func.php` is found.
+ *  - `function`: When a specific theme hook function override is found.
+ *  - `template`: When a template file `*.tpl.php` is found in. Note, if both
+ *    a function and a template are defined, a template implementation will
+ *    always be used and the `function` will be unset.
+ *  - `path`: When a template file `*.tpl.php` is found.
+ *  - `preprocess functions`: When a specific theme hook suggestion function
+ *    `hook_preprocess_HOOK__SUGGESTION` is found.
+ *  - `process functions` When a specific theme hook suggestion function
+ *    `hook_process_HOOK__SUGGESTION` is found.
+ *
+ * @param array $registry
+ *   The theme registry array, passed by reference.
+ * @param string|array $themes
+ *   The name of the theme or list of theme names to process.
+ *
+ * @see bootstrap_theme_registry_alter()
+ * @see _theme_process_registry()
+ * @see _theme_build_registry()
+ */
+function _bootstrap_process_theme_registry(array &$registry, $themes) {
+  // Convert to an array if needed.
+  if (is_string($themes)) {
+    $themes = array();
+  }
+
+  // Processor functions work in two distinct phases with the process
+  // functions always being executed after the preprocess functions.
+  $variable_process_phases = array(
+    'preprocess functions' => 'preprocess',
+    'process functions'    => 'process',
+  );
+
+  // Iterate over each theme passed.
+  // Iterate over the [pre]process phases.
+  foreach ($variable_process_phases as $phase_key => $phase) {
+    foreach ($themes as $theme) {
+      // Get the theme's base path.
+      $path = drupal_get_path('theme', $theme);
+
+      // Find theme function overrides.
+      foreach (drupal_system_listing('/\.(func|vars)\.php$/', $path, 'name', 0) as $name => $file) {
+        // Strip off the extension.
+        if (($pos = strpos($name, '.')) !== FALSE) {
+          $name = substr($name, 0, $pos);
+        }
+
+        // Transform "-" in file names to "_" to match theme hook naming scheme.
+        $hook = strtr($name, '-', '_');
+
+        // File to be included by core's theme function when a theme hook is
+        // invoked.
+        if (isset($registry[$hook])) {
+          if (!isset($registry[$hook]['includes'])) {
+            $registry[$hook]['includes'] = array();
+          }
+
+          // Include the file now so functions can be discovered below.
+          include_once DRUPAL_ROOT . '/' . $file->uri;
+          if (!in_array($file->uri, $registry[$hook]['includes'])) {
+            $registry[$hook]['includes'][] = $file->uri;
+          }
+        }
+      }
+
+      // Process core's normal functionality.
+      _theme_process_registry($registry, $theme, $GLOBALS['theme_key'] === $theme ? 'theme' : 'base_theme', $theme, $path);
+
+      // Find necessary templates in the theme.
+      $registry = drupal_array_merge_deep($registry, drupal_find_theme_templates($registry, '.tpl.php', $path));
+
+      // Iterate over each registered hook.
+      foreach ($registry as $hook => $info) {
+        // Ensure the current phase callback functions array exists.
+        if (!isset($registry[$hook][$phase_key])) {
+          $registry[$hook][$phase_key] = array();
+        }
+
+        // Remove function callbacks if a template was found.
+        if (isset($info['function']) && isset($info['template'])) {
+          unset($registry[$hook]['function']);
+        }
+
+        // Correct template theme paths.
+        if (!isset($info['theme path'])) {
+          $registry[$hook]['theme path'] = $path;
+        }
+
+        // Correct the type that is implementing this override.
+        $registry[$hook]['type'] = $GLOBALS['theme_path'] === $registry[$hook]['theme path'] ? 'theme' : 'base_theme';
+
+        // Sort the phase functions.
+        // @see https://www.drupal.org/node/2098551
+        _bootstrap_registry_sort_phase_functions($registry[$hook][$phase_key], $hook, $phase, $themes);
+
+        // Setup a default "context" variable. This allows #context to be passed
+        // to every template and theme function.
+        // @see https://www.drupal.org/node/2035055
+        if (isset($info['variables']) && !isset($info['variables']['context'])) {
+          $registry[$hook]['variables']['context'] = array();
+        }
+
+        // Setup a default "icon" variable. This allows #icon to be passed
+        // to every template and theme function.
+        // @see https://www.drupal.org/node/2219965
+        if (isset($info['variables']) && !isset($info['variables']['icon'])) {
+          $registry[$hook]['variables']['icon'] = NULL;
+        }
+        if (isset($info['variables']) && !isset($info['variables']['icon_position'])) {
+          $registry[$hook]['variables']['icon_position'] = 'before';
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Ensures the phase functions are invoked in the correct order.
+ *
+ * @param array $functions
+ *   The phase functions to iterate over.
+ * @param string $hook
+ *   The current hook being processed.
+ * @param string $phase
+ *   The current phase being processed.
+ * @param array $themes
+ *   An indexed array of current themes.
+ *
+ * @see https://www.drupal.org/node/2098551
+ */
+function _bootstrap_registry_sort_phase_functions(array &$functions, $hook, $phase, array $themes) {
+  // Immediately return if there is nothing to sort.
+  if (count($functions) < 2) {
+    return;
+  }
+
+  // Create an associative array of theme functions to ensure sort order.
+  $theme_functions = array_fill_keys($themes, array());
+
+  // Iterate over all the themes.
+  foreach ($themes as $theme) {
+    // Only add the function to the array of theme functions if it currently
+    // exists in the $functions array.
+    $function = $theme . '_' . $phase . '_' . $hook;
+    $key = array_search($function, $functions);
+    if ($key !== FALSE) {
+      // Save the theme function to be added later, but sorted.
+      $theme_functions[$theme][] = $function;
+
+      // Remove it from the current $functions array.
+      unset($functions[$key]);
+    }
+  }
+
+  // Iterate over all the captured theme functions and place them back into
+  // the phase functions array.
+  foreach ($theme_functions as $array) {
+    $functions = array_merge($functions, $array);
+  }
+}
+
+/**
+ * Processes registered hooks in the theme registry against list of themes.
+ *
+ * This is used to add the necessary phased functions to theme hook suggestions.
+ * Because it uses get_defined_functions(), it must be invoked after all
+ * includes have been detected and loaded. This is similar to
+ * drupal_find_theme_functions(), however severely modified for Bootstrap based
+ * themes.
+ *
+ * @param array $registry
+ *   The theme registry array, passed by reference.
+ * @param string|array $themes
+ *   The name of the theme or list of theme names to process.
+ *
+ * @see https://www.drupal.org/node/939462
+ * @see drupal_find_theme_functions()
+ */
+function _bootstrap_process_theme_registry_suggestions(array &$registry, $themes) {
+  // Convert to an array if needed.
+  if (is_string($themes)) {
+    $themes = array();
+  }
+
+  // Merge in normal core detections first.
+  $registry = drupal_array_merge_deep($registry, drupal_find_theme_functions($registry, $themes));
+
+  // Processor functions work in two distinct phases with the process
+  // functions always being executed after the preprocess functions.
+  $variable_process_phases = array(
+    'preprocess functions' => 'preprocess',
+    'process functions'    => 'process',
+  );
+
+  $grouped_functions = drupal_group_functions_by_prefix();
+
+  // Iterate over each theme passed.
+  foreach ($themes as $theme) {
+    // Iterate over each registered hook.
+    foreach ($registry as $hook => $info) {
+      // The pattern to match.
+      $pattern = isset($info['pattern']) ? $info['pattern'] : ($hook . '__');
+
+      // Only process hooks that have not explicitly "turned off" patterns.
+      if (empty($pattern)) {
+        continue;
+      }
+
+      // Iterate over the [pre]process phases.
+      foreach ($variable_process_phases as $phase_key => $phase) {
+        // Find functions matching the specific theme and phase prefix.
+        $prefix = $theme . '_' . $phase;
+
+        // Grep only the functions which are within the prefix group.
+        list($first_prefix,) = explode('_', $prefix, 2);
+        if (isset($grouped_functions[$first_prefix]) && ($matches = preg_grep('/^' . $prefix . '_' . $pattern . '/', $grouped_functions[$first_prefix]))) {
+          foreach ($matches as $match) {
+            // Determine the current theme implementation.
+            $hook = substr($match, strlen($prefix) + 1);
+            $base_hook = $hook;
+
+            // If there's no current theme implementation, keep checking for
+            // more generic base hooks. If there's still no implementation,
+            // one must be created using the last found implementation
+            // information.
+            if (!isset($registry[$base_hook]) || isset($registry[$base_hook]['base hook'])) {
+              // Iteratively strip everything after the last '__' delimiter,
+              // until an implementation is found.
+              while ($pos = strrpos($base_hook, '__')) {
+                $base_hook = substr($base_hook, 0, $pos);
+                if (isset($registry[$base_hook])) {
+                  break;
+                }
+              }
+
+              // No base hook was found, this allows the implementation to be
+              // ignored in the next steps.
+              if (!isset($registry[$base_hook])) {
+                $base_hook = FALSE;
+              }
+            }
+
+            // Process specific base hook implementations if necessary.
+            if ($base_hook) {
+              // The matched theme implementation does not exist in the
+              // registry, one must be created if base hook information was
+              // found, otherwise it will be ignored.
+              if (!isset($registry[$hook])) {
+                $registry[$base_hook] += array(
+                  'type' => 'theme',
+                  'preprocess functions' => array(),
+                  'process functions' => array(),
+                );
+                $hook_type = isset($registry[$base_hook]['function']) ? 'function' : 'template';
+                $arg_name = isset($registry[$base_hook]['variables']) ? 'variables' : 'render element';
+                $registry[$hook] = array(
+                  $hook_type => $registry[$base_hook][$hook_type],
+                  $arg_name => $registry[$base_hook][$arg_name],
+                  'base hook' => $base_hook,
+                  'type' => $registry[$base_hook]['type'],
+                  'preprocess functions' => array(),
+                  'process functions' => array(),
+                );
+                if (isset($registry[$base_hook]['path'])) {
+                  $registry[$hook]['path'] = $registry[$base_hook]['path'];
+                }
+                if (isset($registry[$base_hook]['theme path'])) {
+                  $registry[$hook]['theme path'] = $registry[$base_hook]['theme path'];
+                }
+              }
+            }
+
+            // If the hook exists, merge in the functions. Otherwise ignore it
+            // since there was no base hook found and a new implementation
+            // could not be created.
+            if (isset($registry[$hook])) {
+              $registry[$hook] = drupal_array_merge_deep($registry[$hook], array(
+                $phase_key => array($match),
+              ));
+
+              // Due to how theme() functions, if a base hook implements
+              // preprocess or process functions, then the base hook info is
+              // used to invoke the necessary phase functions instead of the
+              // suggestion hook info. To get around this, a helper function
+              // must be appended to the base hook info so it can call the
+              // theme suggestion implementation's phase function.
+              $function = '_bootstrap_' . $phase . '_theme_suggestion';
+              if (!in_array($function, $registry[$base_hook][$phase_key])) {
+                $registry[$base_hook][$phase_key][] = $function;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Performance gain.
+ *
+ * Do not remove from 7.x. This function is not available in every core version.
+ *
+ * @see https://www.drupal.org/node/2339447
+ */
+if (!function_exists('drupal_group_functions_by_prefix')) {
+
+  /**
+   * Group all user functions by word before first underscore.
+   *
+   * @return array
+   *   Functions grouped by the first prefix.
+   */
+  function drupal_group_functions_by_prefix() {
+    $functions = get_defined_functions();
+    $grouped_functions = array();
+
+    // Splitting user defined functions into groups by the first prefix.
+    foreach ($functions['user'] as $function) {
+      list($first_prefix,) = explode('_', $function, 2);
+      $grouped_functions[$first_prefix][] = $function;
+    }
+
+    return $grouped_functions;
+  }
+
+}
+
+/**
+ * @} End of "addtogroup registry".
+ */

+ 182 - 0
mydata/themes/bootstrap/js/bootstrap.admin.js

@@ -0,0 +1,182 @@
+(function ($, Drupal) {
+  /*global jQuery:false */
+  /*global Drupal:false */
+  "use strict";
+
+  /**
+   * Provide vertical tab summaries for Bootstrap settings.
+   */
+  Drupal.behaviors.bootstrapSettingSummaries = {
+    attach: function (context) {
+      var $context = $(context);
+
+      // General.
+      $context.find('#edit-general').drupalSetSummary(function () {
+        var summary = [];
+        // Buttons.
+        var size = $context.find('select[name="bootstrap_button_size"] :selected');
+        if (size.val()) {
+          summary.push(Drupal.t('@size Buttons', {
+            '@size': size.text()
+          }));
+        }
+
+        // Images.
+        var shape = $context.find('select[name="bootstrap_image_shape"] :selected');
+        if (shape.val()) {
+          summary.push(Drupal.t('@shape Images', {
+            '@shape': shape.text()
+          }));
+        }
+        if ($context.find(':input[name="bootstrap_image_responsive"]').is(':checked')) {
+          summary.push(Drupal.t('Responsive Images'));
+        }
+
+        // Tables.
+        if ($context.find(':input[name="bootstrap_table_responsive"]').is(':checked')) {
+          summary.push(Drupal.t('Responsive Tables'));
+        }
+
+        return summary.join(', ');
+
+      });
+
+      // Components.
+      $context.find('#edit-components').drupalSetSummary(function () {
+        var summary = [];
+        // Breadcrumbs.
+        var breadcrumb = parseInt($context.find('select[name="bootstrap_breadcrumb"]').val(), 10);
+        if (breadcrumb) {
+          summary.push(Drupal.t('Breadcrumbs'));
+        }
+        // Navbar.
+        var navbar = 'Navbar: ' + $context.find('select[name="bootstrap_navbar_position"] :selected').text();
+        if ($context.find('input[name="bootstrap_navbar_inverse"]').is(':checked')) {
+          navbar += ' (' + Drupal.t('Inverse') + ')';
+        }
+        summary.push(navbar);
+        return summary.join(', ');
+      });
+
+      // Javascript.
+      $context.find('#edit-javascript').drupalSetSummary(function () {
+        var summary = [];
+        if ($context.find('input[name="bootstrap_anchors_fix"]').is(':checked')) {
+          summary.push(Drupal.t('Anchors'));
+        }
+        if ($context.find('input[name="bootstrap_popover_enabled"]').is(':checked')) {
+          summary.push(Drupal.t('Popovers'));
+        }
+        if ($context.find('input[name="bootstrap_tooltip_enabled"]').is(':checked')) {
+          summary.push(Drupal.t('Tooltips'));
+        }
+        return summary.join(', ');
+      });
+
+      // Advanced.
+      $context.find('#edit-advanced').drupalSetSummary(function () {
+        var summary = [];
+        var $cdnProvider = $context.find('select[name="bootstrap_cdn_provider"] :selected');
+        var cdnProvider = $cdnProvider.val();
+        if ($cdnProvider.length && cdnProvider.length) {
+          summary.push(Drupal.t('CDN provider: %provider', { '%provider': $cdnProvider.text() }));
+
+          // jsDelivr CDN.
+          if (cdnProvider === 'jsdelivr') {
+            var $jsDelivrVersion = $context.find('select[name="bootstrap_cdn_jsdelivr_version"] :selected');
+            if ($jsDelivrVersion.length && $jsDelivrVersion.val().length) {
+              summary.push($jsDelivrVersion.text());
+            }
+            var $jsDelivrTheme = $context.find('select[name="bootstrap_cdn_jsdelivr_theme"] :selected');
+            if ($jsDelivrTheme.length && $jsDelivrTheme.val() !== 'bootstrap') {
+              summary.push($jsDelivrTheme.text());
+            }
+          }
+        }
+        return summary.join(', ');
+      });
+    }
+  };
+
+  /**
+   * Provide BootstrapCDN (via jsDelivr) theme preview.
+   */
+  Drupal.behaviors.bootstrapThemePreview = {
+    attach: function (context) {
+      var $context = $(context);
+      var $preview = $context.find('#bootstrap-theme-preview');
+      $preview.once('bootstrap-theme-preview', function () {
+        // Construct the "Bootstrap Theme" preview here since it's not actually
+        // a Bootswatch theme, but rather one provided by Bootstrap itself.
+        // Unfortunately getbootstrap.com does not have HTTPS enabled, so the
+        // preview image cannot be protocol relative.
+        // @todo Make protocol relative if/when Bootstrap enables HTTPS.
+        $preview.append('<a id="bootstrap-theme-preview-bootstrap_theme" class="bootswatch-preview element-invisible" href="https://getbootstrap.com/docs/3.3/examples/theme/" target="_blank"><img class="img-responsive" src="https://getbootstrap.com/docs/3.3/examples/screenshots/theme.jpg" alt="' + Drupal.t('Preview of the Bootstrap theme') + '" /></a>');
+
+        // Retrieve the Bootswatch theme preview images.
+        // @todo This should be moved into PHP.
+        $.ajax({
+          url: 'https://bootswatch.com/api/3.json',
+          dataType: 'json',
+          success: function (json) {
+            var themes = json.themes;
+            for (var i = 0, len = themes.length; i < len; i++) {
+              $preview.append('<a id="bootstrap-theme-preview-' + themes[i].name.toLowerCase() + '" class="bootswatch-preview element-invisible" href="' + themes[i].preview + '" target="_blank"><img class="img-responsive" src="' + themes[i].thumbnail.replace(/^http:/, 'https:') + '" alt="' + Drupal.t('Preview of the @title Bootswatch theme', { '@title': themes[i].name }) + '" /></a>');
+            }
+          },
+          complete: function () {
+            $preview.parent().find('select[name="bootstrap_cdn_jsdelivr_theme"]').bind('change', function () {
+              $preview.find('.bootswatch-preview').addClass('element-invisible');
+              if ($(this).val().length) {
+                $preview.find('#bootstrap-theme-preview-' + $(this).val()).removeClass('element-invisible');
+              }
+            }).change();
+          }
+        });
+      });
+    }
+  };
+
+  /**
+   * Provide Bootstrap navbar preview.
+   */
+  Drupal.behaviors.bootstrapNavbarPreview = {
+    attach: function (context) {
+      var $context = $(context);
+      var $preview = $context.find('#edit-navbar');
+      $preview.once('navbar', function () {
+        var $body = $context.find('body');
+        var $navbar = $context.find('#navbar.navbar');
+        $preview.find('select[name="bootstrap_navbar_position"]').bind('change', function () {
+          var $position = $(this).find(':selected').val();
+          $navbar.removeClass('navbar-fixed-bottom navbar-fixed-top navbar-static-top container');
+          if ($position.length) {
+            $navbar.addClass('navbar-'+ $position);
+          }
+          else {
+            $navbar.addClass('container');
+          }
+          // Apply appropriate classes to body.
+          $body.removeClass('navbar-is-fixed-top navbar-is-fixed-bottom navbar-is-static-top');
+          switch ($position) {
+            case 'fixed-top':
+              $body.addClass('navbar-is-fixed-top');
+              break;
+
+            case 'fixed-bottom':
+              $body.addClass('navbar-is-fixed-bottom');
+              break;
+
+            case 'static-top':
+              $body.addClass('navbar-is-static-top');
+              break;
+          }
+        });
+        $preview.find('input[name="bootstrap_navbar_inverse"]').bind('change', function () {
+          $navbar.toggleClass('navbar-inverse navbar-default');
+        });
+      });
+    }
+  };
+
+})(jQuery, Drupal);

+ 281 - 0
mydata/themes/bootstrap/js/bootstrap.js

@@ -0,0 +1,281 @@
+/**
+ * @file
+ * bootstrap.js
+ *
+ * Provides general enhancements and fixes to Bootstrap's JS files.
+ */
+
+var Drupal = Drupal || {};
+
+(function($, Drupal){
+  "use strict";
+
+  var $document = $(document);
+
+  Drupal.behaviors.bootstrap = {
+    attach: function(context) {
+      // Provide some Bootstrap tab/Drupal integration.
+      $(context).find('.tabbable').once('bootstrap-tabs', function () {
+        var $wrapper = $(this);
+        var $tabs = $wrapper.find('.nav-tabs');
+        var $content = $wrapper.find('.tab-content');
+        var borderRadius = parseInt($content.css('borderBottomRightRadius'), 10);
+        var bootstrapTabResize = function() {
+          if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
+            $content.css('min-height', $tabs.outerHeight());
+          }
+        };
+        // Add min-height on content for left and right tabs.
+        bootstrapTabResize();
+        // Detect tab switch.
+        if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
+          $tabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
+            bootstrapTabResize();
+            if ($wrapper.hasClass('tabs-left')) {
+              if ($(e.target).parent().is(':first-child')) {
+                $content.css('borderTopLeftRadius', '0');
+              }
+              else {
+                $content.css('borderTopLeftRadius', borderRadius + 'px');
+              }
+            }
+            else {
+              if ($(e.target).parent().is(':first-child')) {
+                $content.css('borderTopRightRadius', '0');
+              }
+              else {
+                $content.css('borderTopRightRadius', borderRadius + 'px');
+              }
+            }
+          });
+        }
+      });
+    }
+  };
+
+  /**
+   * Behavior for .
+   */
+  Drupal.behaviors.bootstrapFormHasError = {
+    attach: function (context, settings) {
+      if (settings.bootstrap && settings.bootstrap.formHasError) {
+        var $context = $(context);
+        $context.find('.form-item.has-error:not(.form-type-password.has-feedback)').once('error', function () {
+          var $formItem = $(this);
+          var $input = $formItem.find(':input');
+          $input.on('keyup focus blur', function () {
+            var value = $input.val() || false;
+            $formItem[value ? 'removeClass' : 'addClass']('has-error');
+            $input[value ? 'removeClass' : 'addClass']('error');
+          });
+        });
+      }
+    }
+  };
+
+  /**
+   * Bootstrap Popovers.
+   */
+  Drupal.behaviors.bootstrapPopovers = {
+    attach: function (context, settings) {
+      // Immediately return if popovers are not available.
+      if (!settings.bootstrap || !settings.bootstrap.popoverEnabled || !$.fn.popover) {
+        return;
+      }
+
+      // Popover autoclose.
+      if (settings.bootstrap.popoverOptions.triggerAutoclose) {
+        var $currentPopover = null;
+        $document
+          .on('show.bs.popover', '[data-toggle=popover]', function () {
+            var $trigger = $(this);
+            var popover = $trigger.data('bs.popover');
+
+            // Only keep track of clicked triggers that we're manually handling.
+            if (popover.options.originalTrigger === 'click') {
+              if ($currentPopover && !$currentPopover.is($trigger)) {
+                $currentPopover.popover('hide');
+              }
+              $currentPopover = $trigger;
+            }
+          })
+          .on('click', function (e) {
+            var $target = $(e.target);
+            var popover = $target.is('[data-toggle=popover]') && $target.data('bs.popover');
+            if ($currentPopover && !$target.is('[data-toggle=popover]') && !$target.closest('.popover.in')[0]) {
+              $currentPopover.popover('hide');
+              $currentPopover = null;
+            }
+          })
+        ;
+      }
+
+      var elements = $(context).find('[data-toggle=popover]').toArray();
+      for (var i = 0; i < elements.length; i++) {
+        var $element = $(elements[i]);
+        var options = $.extend({}, $.fn.popover.Constructor.DEFAULTS, settings.bootstrap.popoverOptions, $element.data());
+
+        // Store the original trigger.
+        options.originalTrigger = options.trigger;
+
+        // If the trigger is "click", then we'll handle it manually here.
+        if (options.trigger === 'click') {
+          options.trigger = 'manual';
+        }
+
+        // Retrieve content from a target element.
+        var target = options.target || $element.is('a[href^="#"]') && $element.attr('href');
+        var $target = $document.find(target).clone();
+        if (!options.content && $target[0]) {
+          $target.removeClass('element-invisible hidden').removeAttr('aria-hidden');
+          options.content = $target.wrap('<div/>').parent()[options.html ? 'html' : 'text']() || '';
+        }
+
+        // Initialize the popover.
+        $element.popover(options);
+
+        // Handle clicks manually.
+        if (options.originalTrigger === 'click') {
+          // To ensure the element is bound multiple times, remove any
+          // previously set event handler before adding another one.
+          $element
+            .off('click.drupal.bootstrap.popover')
+            .on('click.drupal.bootstrap.popover', function (e) {
+              $(this).popover('toggle');
+              e.preventDefault();
+              e.stopPropagation();
+            })
+          ;
+        }
+      }
+    },
+    detach: function (context, settings) {
+      // Immediately return if popovers are not available.
+      if (!settings.bootstrap || !settings.bootstrap.popoverEnabled || !$.fn.popover) {
+        return;
+      }
+
+      // Destroy all popovers.
+      $(context).find('[data-toggle="popover"]')
+        .off('click.drupal.bootstrap.popover')
+        .popover('destroy')
+      ;
+    }
+  };
+
+  /**
+   * Bootstrap Tooltips.
+   */
+  Drupal.behaviors.bootstrapTooltips = {
+    attach: function (context, settings) {
+      if (settings.bootstrap && settings.bootstrap.tooltipEnabled) {
+        var elements = $(context).find('[data-toggle="tooltip"]').toArray();
+        for (var i = 0; i < elements.length; i++) {
+          var $element = $(elements[i]);
+          var options = $.extend({}, settings.bootstrap.tooltipOptions, $element.data());
+          $element.tooltip(options);
+        }
+      }
+    }
+  };
+
+  /**
+   * Anchor fixes.
+   */
+  var $scrollableElement = $();
+  Drupal.behaviors.bootstrapAnchors = {
+    attach: function(context, settings) {
+      var i, elements = ['html', 'body'];
+      if (!$scrollableElement.length) {
+        for (i = 0; i < elements.length; i++) {
+          var $element = $(elements[i]);
+          if ($element.scrollTop() > 0) {
+            $scrollableElement = $element;
+            break;
+          }
+          else {
+            $element.scrollTop(1);
+            if ($element.scrollTop() > 0) {
+              $element.scrollTop(0);
+              $scrollableElement = $element;
+              break;
+            }
+          }
+        }
+      }
+      if (!settings.bootstrap || settings.bootstrap.anchorsFix !== '1') {
+        return;
+      }
+      var anchors = $(context).find('a').toArray();
+      for (i = 0; i < anchors.length; i++) {
+        if (!anchors[i].scrollTo) {
+          this.bootstrapAnchor(anchors[i]);
+        }
+      }
+      $scrollableElement.once('bootstrap-anchors', function () {
+        $scrollableElement.on('click.bootstrap-anchors', 'a[href*="#"]:not([data-toggle],[data-target],[data-slide])', function(e) {
+          if (this.scrollTo) {
+            this.scrollTo(e);
+          }
+        });
+      });
+    },
+    bootstrapAnchor: function (element) {
+      element.validAnchor = element.nodeName === 'A' && (location.hostname === element.hostname || !element.hostname) && (element.hash.replace(/#/,'').length > 0);
+      element.scrollTo = function(event) {
+        var attr = 'id';
+        var $target = $(element.hash);
+        // Check for anchors that use the name attribute instead.
+        if (!$target.length) {
+          attr = 'name';
+          $target = $('[name="' + element.hash.replace('#', '') + '"]');
+        }
+        // Immediately stop if no anchors are found.
+        if (!this.validAnchor && !$target.length) {
+          return;
+        }
+        // Anchor is valid, continue if there is an offset.
+        var offset = $target.offset().top - parseInt($scrollableElement.css('paddingTop'), 10) - parseInt($scrollableElement.css('marginTop'), 10);
+        if (offset > 0) {
+          if (event) {
+            event.preventDefault();
+          }
+          var $fakeAnchor = $('<div/>')
+            .addClass('element-invisible')
+            .attr(attr, $target.attr(attr))
+            .css({
+              position: 'absolute',
+              top: offset + 'px',
+              zIndex: -1000
+            })
+            .appendTo($scrollableElement);
+          $target.removeAttr(attr);
+          var complete = function () {
+            location.hash = element.hash;
+            $fakeAnchor.remove();
+            $target.attr(attr, element.hash.replace('#', ''));
+          };
+          if (Drupal.settings.bootstrap.anchorsSmoothScrolling) {
+            $scrollableElement.animate({ scrollTop: offset, avoidTransforms: true }, 400, complete);
+          }
+          else {
+            $scrollableElement.scrollTop(offset);
+            complete();
+          }
+        }
+      };
+    }
+  };
+
+  /**
+   * Tabledrag theming elements.
+   */
+  Drupal.theme.tableDragChangedMarker = function () {
+    return '<span class="tabledrag-changed glyphicon glyphicon-warning-sign text-warning"></span>';
+  };
+
+  Drupal.theme.tableDragChangedWarning = function () {
+    return '<div class="tabledrag-changed-warning alert alert-warning messages warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('Changes made in this table will not be saved until the form is submitted.') + '</div>';
+  };
+
+})(jQuery, Drupal);

+ 86 - 0
mydata/themes/bootstrap/js/misc/_collapse.js

@@ -0,0 +1,86 @@
+(function ($) {
+
+/**
+ * Toggle the visibility of a fieldset using smooth animations.
+ */
+Drupal.toggleFieldset = function (fieldset) {
+  var $toggle = $($(fieldset).find('[data-toggle=collapse]').data('target'));
+  if ($toggle.length) {
+    $toggle.collapse('toggle');
+  }
+};
+
+/**
+ * Scroll a given fieldset into view as much as possible.
+ */
+Drupal.collapseScrollIntoView = function (node) {
+  var h = document.documentElement.clientHeight || document.body.clientHeight || 0;
+  var offset = document.documentElement.scrollTop || document.body.scrollTop || 0;
+  var posY = $(node).offset().top;
+  var fudge = 55;
+  if (posY + node.offsetHeight + fudge > h + offset) {
+    if (node.offsetHeight > h) {
+      window.scrollTo(0, posY);
+    }
+    else {
+      window.scrollTo(0, posY + node.offsetHeight - h + fudge);
+    }
+  }
+};
+
+Drupal.behaviors.collapse = {
+  attach: function (context, settings) {
+    $('fieldset.collapsible', context).once('collapse', function () {
+      var $fieldset = $(this);
+      var $body = $fieldset.find('> .panel-collapse');
+      // Expand fieldset if there are errors inside, or if it contains an
+      // element that is targeted by the URI fragment identifier.
+      var anchor = location.hash && location.hash != '#' ? ', ' + location.hash : '';
+      if ($fieldset.find('.error' + anchor).length) {
+        $fieldset.removeClass('collapsed');
+        $body.removeClass('collapsed');
+      }
+
+      var summary = $('<span class="summary"></span>');
+      $fieldset.
+        bind('summaryUpdated', function () {
+          var text = $.trim($fieldset.drupalGetSummary());
+          summary.html(text ? ' (' + text + ')' : '');
+        })
+        .trigger('summaryUpdated');
+
+      // Turn the legend into a clickable link, but retain span.fieldset-legend
+      // for CSS positioning.
+      var $legend = $('> legend .fieldset-legend', this);
+
+      $('<span class="fieldset-legend-prefix element-invisible"></span>')
+        .append($fieldset.hasClass('collapsed') ? Drupal.t('Show') : Drupal.t('Hide'))
+        .prependTo($legend);
+
+      // Bind Bootstrap events with Drupal core events.
+      $fieldset
+        .append(summary)
+        .on('show.bs.collapse', function () {
+          $fieldset
+            .removeClass('collapsed')
+            .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
+          $body.removeClass('collapsed');
+        })
+        .on('shown.bs.collapse', function () {
+          $fieldset.trigger({ type: 'collapsed', value: false });
+          Drupal.collapseScrollIntoView($fieldset.get(0));
+        })
+        .on('hide.bs.collapse', function () {
+          $fieldset
+            .addClass('collapsed')
+            .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Show'));
+          $body.addClass('collapsed');
+        })
+        .on('hidden.bs.collapse', function () {
+          $fieldset.trigger({ type: 'collapsed', value: true });
+        });
+    });
+  }
+};
+
+})(jQuery);

+ 110 - 0
mydata/themes/bootstrap/js/misc/_progress.js

@@ -0,0 +1,110 @@
+(function ($) {
+
+/**
+ * A progressbar object. Initialized with the given id. Must be inserted into
+ * the DOM afterwards through progressBar.element.
+ *
+ * method is the function which will perform the HTTP request to get the
+ * progress bar state. Either "GET" or "POST".
+ *
+ * e.g. pb = new progressBar('myProgressBar');
+ *      some_element.appendChild(pb.element);
+ */
+Drupal.progressBar = function (id, updateCallback, method, errorCallback) {
+  var pb = this;
+  this.id = id;
+  this.method = method || 'GET';
+  this.updateCallback = updateCallback;
+  this.errorCallback = errorCallback;
+
+  // The WAI-ARIA setting aria-live="polite" will announce changes after users
+  // have completed their current activity and not interrupt the screen reader.
+  this.element = $('<div class="progress-wrapper" aria-live="polite"></div>');
+  this.element.html('<div id ="' + id + '" class="progress progress-striped active">' +
+                    '<div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">' +
+                    '<div class="percentage sr-only"></div>' +
+                    '</div></div>' +
+                    '</div><div class="percentage pull-right"></div>' +
+                    '<div class="message">&nbsp;</div>');
+};
+
+/**
+ * Set the percentage and status message for the progressbar.
+ */
+Drupal.progressBar.prototype.setProgress = function (percentage, message) {
+  if (percentage >= 0 && percentage <= 100) {
+    $('div.progress-bar', this.element).css('width', percentage + '%');
+    $('div.progress-bar', this.element).attr('aria-valuenow', percentage);
+    $('div.percentage', this.element).html(percentage + '%');
+  }
+  $('div.message', this.element).html(message);
+  if (this.updateCallback) {
+    this.updateCallback(percentage, message, this);
+  }
+};
+
+/**
+ * Start monitoring progress via Ajax.
+ */
+Drupal.progressBar.prototype.startMonitoring = function (uri, delay) {
+  this.delay = delay;
+  this.uri = uri;
+  this.sendPing();
+};
+
+/**
+ * Stop monitoring progress via Ajax.
+ */
+Drupal.progressBar.prototype.stopMonitoring = function () {
+  clearTimeout(this.timer);
+  // This allows monitoring to be stopped from within the callback.
+  this.uri = null;
+};
+
+/**
+ * Request progress data from server.
+ */
+Drupal.progressBar.prototype.sendPing = function () {
+  if (this.timer) {
+    clearTimeout(this.timer);
+  }
+  if (this.uri) {
+    var pb = this;
+    // When doing a post request, you need non-null data. Otherwise a
+    // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
+    $.ajax({
+      type: this.method,
+      url: this.uri,
+      data: '',
+      dataType: 'json',
+      success: function (progress) {
+        // Display errors.
+        if (progress.status == 0) {
+          pb.displayError(progress.data);
+          return;
+        }
+        // Update display.
+        pb.setProgress(progress.percentage, progress.message);
+        // Schedule next timer.
+        pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay);
+      },
+      error: function (xmlhttp) {
+        pb.displayError(Drupal.ajaxError(xmlhttp, pb.uri));
+      }
+    });
+  }
+};
+
+/**
+ * Display errors on the page.
+ */
+Drupal.progressBar.prototype.displayError = function (string) {
+  var error = $('<div class="alert alert-block alert-error"><a class="close" data-dismiss="alert" href="#">&times;</a><h4>Error message</h4></div>').append(string);
+  $(this.element).before(error).hide();
+
+  if (this.errorCallback) {
+    this.errorCallback(this);
+  }
+};
+
+})(jQuery);

+ 203 - 0
mydata/themes/bootstrap/js/misc/_vertical-tabs.js

@@ -0,0 +1,203 @@
+
+(function ($) {
+
+/**
+ * This script transforms a set of fieldsets into a stack of vertical
+ * tabs. Another tab pane can be selected by clicking on the respective
+ * tab.
+ *
+ * Each tab may have a summary which can be updated by another
+ * script. For that to work, each fieldset has an associated
+ * 'verticalTabCallback' (with jQuery.data() attached to the fieldset),
+ * which is called every time the user performs an update to a form
+ * element inside the tab pane.
+ */
+Drupal.behaviors.verticalTabs = {
+  attach: function (context) {
+    $('.vertical-tabs-panes', context).once('vertical-tabs', function () {
+      $(this).addClass('tab-content');
+      var focusID = $(':hidden.vertical-tabs-active-tab', this).val();
+      if (typeof focusID === 'undefined' || !focusID.length) {
+        focusID = false;
+      }
+      var tab_focus;
+
+      // Check if there are some fieldsets that can be converted to vertical-tabs
+      var $fieldsets = $('> fieldset', this);
+      if ($fieldsets.length == 0) {
+        return;
+      }
+
+      // Create the tab column.
+      var tab_list = $('<ul class="nav nav-tabs vertical-tabs-list"></ul>');
+      $(this).wrap('<div class="tabbable tabs-left vertical-tabs clearfix"></div>').before(tab_list);
+
+      // Transform each fieldset into a tab.
+      $fieldsets.each(function () {
+        var vertical_tab = new Drupal.verticalTab({
+          title: $('> legend', this).text(),
+          fieldset: $(this)
+        });
+        tab_list.append(vertical_tab.item);
+        $(this)
+          .removeClass('collapsible collapsed panel panel-default')
+          .addClass('tab-pane vertical-tabs-pane')
+          .data('verticalTab', vertical_tab)
+          .find('> legend').remove();
+        $(this).find('> div').removeClass('panel-collapse collapse').addClass('fade');
+        if (this.id === focusID) {
+          tab_focus = $(this);
+        }
+      });
+
+      $('> li:first', tab_list).addClass('first');
+      $('> li:last', tab_list).addClass('last');
+
+      if (!tab_focus) {
+        // If the current URL has a fragment and one of the tabs contains an
+        // element that matches the URL fragment, activate that tab.
+        if (window.location.hash && $(this).find(window.location.hash).length) {
+          tab_focus = $(this).find(window.location.hash).closest('.vertical-tabs-pane');
+        }
+        else {
+          tab_focus = $('> .vertical-tabs-pane:first', this);
+        }
+      }
+      if (tab_focus.length) {
+        tab_focus.data('verticalTab').focus();
+      }
+    });
+  }
+};
+
+/**
+ * The vertical tab object represents a single tab within a tab group.
+ *
+ * @param settings
+ *   An object with the following keys:
+ *   - title: The name of the tab.
+ *   - fieldset: The jQuery object of the fieldset that is the tab pane.
+ */
+Drupal.verticalTab = function (settings) {
+  var self = this;
+  $.extend(this, settings, Drupal.theme('verticalTab', settings));
+
+  this.link.click(function () {
+    self.focus();
+  });
+
+  // Keyboard events added:
+  // Pressing the Enter key will open the tab pane.
+  this.link.keydown(function(event) {
+    if (event.keyCode == 13) {
+      self.focus();
+      // Set focus on the first input field of the visible fieldset/tab pane.
+      $("fieldset.vertical-tabs-pane :input:visible:enabled:first").focus();
+      return false;
+    }
+  });
+
+  this.fieldset
+    .bind('summaryUpdated', function () {
+      self.updateSummary();
+    })
+    .trigger('summaryUpdated');
+};
+
+Drupal.verticalTab.prototype = {
+  /**
+   * Displays the tab's content pane.
+   */
+  focus: function () {
+    this.fieldset
+      .siblings('fieldset.vertical-tabs-pane')
+        .each(function () {
+          $(this).removeClass('active').find('> div').removeClass('in');
+          var tab = $(this).data('verticalTab');
+          tab.item.removeClass('selected');
+        })
+        .end()
+        .addClass('active')
+        .attr('style', '')
+        .siblings(':hidden.vertical-tabs-active-tab')
+        .val(this.fieldset.attr('id'));
+    this.fieldset.find('> div').addClass('in');
+    this.fieldset.data('verticalTab').item.find('a').tab('show');
+    this.item.addClass('selected');
+    // Mark the active tab for screen readers.
+    $('#active-vertical-tab').remove();
+    this.link.append('<span id="active-vertical-tab" class="element-invisible">' + Drupal.t('(active tab)') + '</span>');
+  },
+
+  /**
+   * Updates the tab's summary.
+   */
+  updateSummary: function () {
+    this.summary.html(this.fieldset.drupalGetSummary());
+  },
+
+  /**
+   * Shows a vertical tab pane.
+   */
+  tabShow: function () {
+    // Display the tab.
+    this.item.show();
+    // Update .first marker for items. We need recurse from parent to retain the
+    // actual DOM element order as jQuery implements sortOrder, but not as public
+    // method.
+    this.item.parent().children('.vertical-tab-button').removeClass('first')
+      .filter(':visible:first').addClass('first');
+    // Display the fieldset.
+    this.fieldset.removeClass('vertical-tab-hidden');
+    // Focus this tab.
+    this.focus();
+    return this;
+  },
+
+  /**
+   * Hides a vertical tab pane.
+   */
+  tabHide: function () {
+    // Hide this tab.
+    this.item.hide();
+    // Update .first marker for items. We need recurse from parent to retain the
+    // actual DOM element order as jQuery implements sortOrder, but not as public
+    // method.
+    this.item.parent().children('.vertical-tab-button').removeClass('first')
+      .filter(':visible:first').addClass('first');
+    // Hide the fieldset.
+    this.fieldset.addClass('vertical-tab-hidden');
+    // Focus the first visible tab (if there is one).
+    var $firstTab = this.fieldset.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
+    if ($firstTab.length) {
+      $firstTab.data('verticalTab').focus();
+    }
+    return this;
+  }
+};
+
+/**
+ * Theme function for a vertical tab.
+ *
+ * @param settings
+ *   An object with the following keys:
+ *   - title: The name of the tab.
+ * @return
+ *   This function has to return an object with at least these keys:
+ *   - item: The root tab jQuery element
+ *   - link: The anchor tag that acts as the clickable area of the tab
+ *       (jQuery version)
+ *   - summary: The jQuery element that contains the tab summary
+ */
+Drupal.theme.prototype.verticalTab = function (settings) {
+  var tab = {};
+  tab.item = $('<li class="vertical-tab-button" tabindex="-1"></li>')
+    .append(tab.link = $('<a href="#' + settings.fieldset[0].id + '" data-toggle="tab"></a>')
+      .append(tab.title = $('<span></span>').text(settings.title))
+      .append(tab.summary = $('<div class="summary"></div>')
+    )
+  );
+  return tab;
+};
+
+})(jQuery);

+ 88 - 0
mydata/themes/bootstrap/js/misc/ajax.js

@@ -0,0 +1,88 @@
+(function ($) {
+
+/**
+ * Override Drupal's AJAX prototype beforeSend function so it can append the
+ * throbber inside the pager links.
+ */
+Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) {
+  // For forms without file inputs, the jQuery Form plugin serializes the form
+  // values, and then calls jQuery's $.ajax() function, which invokes this
+  // handler. In this circumstance, options.extraData is never used. For forms
+  // with file inputs, the jQuery Form plugin uses the browser's normal form
+  // submission mechanism, but captures the response in a hidden IFRAME. In this
+  // circumstance, it calls this handler first, and then appends hidden fields
+  // to the form to submit the values in options.extraData. There is no simple
+  // way to know which submission mechanism will be used, so we add to extraData
+  // regardless, and allow it to be ignored in the former case.
+  if (this.form) {
+    options.extraData = options.extraData || {};
+
+    // Let the server know when the IFRAME submission mechanism is used. The
+    // server can use this information to wrap the JSON response in a TEXTAREA,
+    // as per http://jquery.malsup.com/form/#file-upload.
+    options.extraData.ajax_iframe_upload = '1';
+
+    // The triggering element is about to be disabled (see below), but if it
+    // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that
+    // value is included in the submission. As per above, submissions that use
+    // $.ajax() are already serialized prior to the element being disabled, so
+    // this is only needed for IFRAME submissions.
+    var v = $.fieldValue(this.element);
+    if (v !== null) {
+      options.extraData[this.element.name] = v;
+    }
+  }
+
+  var $element = $(this.element);
+
+  // Disable the element that received the change to prevent user interface
+  // interaction while the Ajax request is in progress. ajax.ajaxing prevents
+  // the element from triggering a new request, but does not prevent the user
+  // from changing its value.
+  $element.addClass('progress-disabled').attr('disabled', true);
+
+  // Insert progressbar or throbber.
+  if (this.progress.type == 'bar') {
+    var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
+    if (this.progress.message) {
+      progressBar.setProgress(-1, this.progress.message);
+    }
+    if (this.progress.url) {
+      progressBar.startMonitoring(this.progress.url, this.progress.interval || 500);
+    }
+    this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar');
+    this.progress.object = progressBar;
+    if (!$element.closest('.file-widget,.form-item').length) {
+      $element.before(this.progress.element);
+    }
+    else {
+      $element.closest('.file-widget,.form-item').after(this.progress.element);
+    }
+  }
+  else if (this.progress.type == 'throbber') {
+    this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><i class="glyphicon glyphicon-refresh glyphicon-spin"></i></div>');
+    if (this.progress.message) {
+      $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
+    }
+
+    // If element is an input type, append after.
+    if ($element.is('input')) {
+      $element.after(this.progress.element);
+    }
+    else if ($element.is('select')) {
+      var $inputGroup = $element.closest('.form-item').find('.input-group-addon, .input-group-btn');
+      if (!$inputGroup.length) {
+        $element.wrap('<div class="input-group">');
+        $inputGroup = $('<span class="input-group-addon">');
+        $element.after($inputGroup);
+      }
+      $inputGroup.append(this.progress.element);
+    }
+    // Otherwise append the throbber inside the element.
+    else {
+      $element.append(this.progress.element);
+    }
+  }
+};
+
+})(jQuery);

+ 252 - 0
mydata/themes/bootstrap/js/misc/autocomplete.js

@@ -0,0 +1,252 @@
+(function ($) {
+
+  /**
+   * Attaches the autocomplete behavior to all required fields.
+   */
+  Drupal.behaviors.autocomplete = {
+    attach: function (context) {
+      var $context = $(context);
+      var acdb = [];
+      $context.find('input.autocomplete').once('autocomplete', function () {
+        var uri = this.value;
+        if (!acdb[uri]) {
+          acdb[uri] = new Drupal.ACDB(uri);
+        }
+        var $input = $context.find('#' + this.id.substr(0, this.id.length - 13))
+          .attr('autocomplete', 'OFF')
+          .attr('aria-autocomplete', 'list');
+        $context.find($input[0].form).submit(Drupal.autocompleteSubmit);
+        $input.parents('.form-item')
+          .attr('role', 'application')
+          .append($('<span class="element-invisible" aria-live="assertive"></span>')
+            .attr('id', $input.attr('id') + '-autocomplete-aria-live')
+          );
+        new Drupal.jsAC($input, acdb[uri], $context);
+      });
+    }
+  };
+
+  /**
+   * Prevents the form from submitting if the suggestions popup is open
+   * and closes the suggestions popup when doing so.
+   */
+  Drupal.autocompleteSubmit = function () {
+    // NOTE: Do not return true as this is non-standard. Keep it similar to
+    // core. If another contrib project alters this functionality, then it is
+    // the responsibility of a sub-theme to override this method and combine
+    // this project with the other project.
+    return $('.form-autocomplete > .dropdown').each(function () {
+      this.owner.hidePopup();
+    }).length == 0;
+  };
+
+  /**
+   * Highlights a suggestion.
+   */
+  Drupal.jsAC.prototype.highlight = function (node) {
+    if (this.selected) {
+      $(this.selected).removeClass('active');
+    }
+    $(node).addClass('active');
+    this.selected = node;
+    $(this.ariaLive).html($(this.selected).html());
+  };
+
+  /**
+   * Unhighlights a suggestion.
+   */
+  Drupal.jsAC.prototype.unhighlight = function (node) {
+    $(node).removeClass('active');
+    this.selected = false;
+    $(this.ariaLive).empty();
+  };
+
+  /**
+   * Positions the suggestions popup and starts a search.
+   */
+  Drupal.jsAC.prototype.populatePopup = function () {
+    var $input = $(this.input);
+    // Show popup.
+    if (this.popup) {
+      $(this.popup).remove();
+    }
+    this.selected = false;
+    this.popup = $('<div class="dropdown"></div>')[0];
+    this.popup.owner = this;
+    $input.parent().after(this.popup);
+
+    // Do search.
+    this.db.owner = this;
+    this.db.search(this.input.value);
+  };
+
+  /**
+   * Fills the suggestion popup with any matches received.
+   */
+  Drupal.jsAC.prototype.found = function (matches) {
+    // If no value in the textfield, do not show the popup.
+    if (!this.input.value.length) {
+      return false;
+    }
+
+    // Prepare matches.
+    var ul = $('<ul class="dropdown-menu"></ul>');
+    var ac = this;
+    ul.css({
+      display: 'block',
+      right: 0
+    });
+    for (var key in matches) {
+      $('<li></li>')
+        .html($('<a href="#"></a>').html(matches[key]).on('click', function (e) {
+          e.preventDefault();
+        }))
+        .on('mousedown', function () {
+          ac.hidePopup(this);
+        })
+        .on('mouseover', function () {
+          ac.highlight(this);
+        })
+        .on('mouseout', function () {
+          ac.unhighlight(this);
+        })
+        .data('autocompleteValue', key)
+        .appendTo(ul);
+    }
+
+    // Show popup with matches, if any.
+    if (this.popup) {
+      if (ul.children().length) {
+        $(this.popup).empty().append(ul).show();
+        $(this.ariaLive).html(Drupal.t('Autocomplete popup'));
+      }
+      else {
+        $(this.popup).css({visibility: 'hidden'});
+        this.hidePopup();
+      }
+    }
+  };
+
+  /**
+   * Finds the next sibling item.
+   */
+  Drupal.jsAC.prototype.findNextSibling = function (element) {
+    var sibling = element && element.nextSibling;
+    if (sibling && !this.validItem(sibling)) {
+      return this.findNextSibling(sibling.nextSibling);
+    }
+    return sibling;
+  };
+
+  /**
+   * Finds the previous sibling item.
+   */
+  Drupal.jsAC.prototype.findPreviousSibling = function (element) {
+    var sibling = element && element.previousSibling;
+    if (sibling && !this.validItem(sibling)) {
+      return this.findPreviousSibling(sibling.previousSibling);
+    }
+    return sibling;
+  };
+
+  /**
+   * Highlights the next suggestion.
+   */
+  Drupal.jsAC.prototype.selectDown = function () {
+    var sibling = this.findNextSibling(this.selected);
+    if (sibling) {
+      this.highlight(sibling);
+    }
+    else if (this.popup) {
+      var lis = $('li', this.popup);
+      if (lis.length > 0) {
+        if (this.validItem(lis[0])) {
+          this.highlight(lis[0]);
+        }
+        else {
+          this.highlight(this.findNextSibling(lis[0]));
+        }
+      }
+    }
+  };
+
+  /**
+   * Highlights the previous suggestion.
+   */
+  Drupal.jsAC.prototype.selectUp = function () {
+    var sibling = this.findPreviousSibling(this.selected);
+    if (sibling) {
+      this.highlight(sibling);
+    }
+    else if (this.popup) {
+      var lis = $('li', this.popup);
+      if (lis.length > 0) {
+        if (this.validItem(lis[lis.length - 1])) {
+          this.highlight(lis[lis.length - 1]);
+        }
+        else {
+          this.highlight(this.findPreviousSibling(lis[lis.length - 1]));
+        }
+      }
+    }
+  };
+
+  /**
+   * Ensures the item is valid.
+   */
+  Drupal.jsAC.prototype.validItem = function (element) {
+    return !$(element).is('.dropdown-header, .divider, .disabled');
+  };
+
+  Drupal.jsAC.prototype.setStatus = function (status) {
+    var $throbber = $(this.input).parent().find('.glyphicon-refresh, .autocomplete-throbber').first();
+    var throbbingClass = $throbber.is('.autocomplete-throbber') ? 'throbbing' : 'glyphicon-spin';
+    switch (status) {
+      case 'begin':
+        $throbber.addClass(throbbingClass);
+        $(this.ariaLive).html(Drupal.t('Searching for matches...'));
+        break;
+      case 'cancel':
+      case 'error':
+      case 'found':
+        $throbber.removeClass(throbbingClass);
+        break;
+    }
+  };
+
+  // Save the previous autocomplete prototype.
+  var oldPrototype = Drupal.jsAC.prototype;
+
+  /**
+   * Override the autocomplete constructor.
+   */
+  Drupal.jsAC = function ($input, db, context) {
+    var ac = this;
+
+    // Context is normally passed by Drupal.behaviors.autocomplete above. However,
+    // if a module has manually invoked this method they will likely not know
+    // about this feature and a global fallback context to document must be used.
+    // @see https://www.drupal.org/node/2594243
+    // @see https://www.drupal.org/node/2315295
+    this.$context = context && $(context) || $(document);
+
+    this.input = $input[0];
+    this.ariaLive = this.$context.find('#' + this.input.id + '-autocomplete-aria-live');
+    this.db = db;
+    $input
+      .keydown(function (event) {
+        return ac.onkeydown(this, event);
+      })
+      .keyup(function (event) {
+        ac.onkeyup(this, event);
+      })
+      .blur(function () {
+        ac.hidePopup();
+        ac.db.cancel();
+      });
+  };
+
+  // Restore the previous prototype.
+  Drupal.jsAC.prototype = oldPrototype;
+
+})(jQuery);

+ 24 - 0
mydata/themes/bootstrap/js/misc/states.js

@@ -0,0 +1,24 @@
+(function($) {
+  // Unbind core state.js from document first so we can then override below.
+  $(document).unbind('state:disabled');
+
+  /**
+   * Global state change handlers. These are bound to "document" to cover all
+   * elements whose state changes. Events sent to elements within the page
+   * bubble up to these handlers. We use this system so that themes and modules
+   * can override these state change handlers for particular parts of a page.
+   */
+  $(document).bind('state:disabled', function(e) {
+    // Only act when this change was triggered by a dependency and not by the
+    // element monitoring itself.
+    if (e.trigger) {
+      $(e.target)
+        .attr('disabled', e.value)
+        .closest('.form-item, .form-submit, .form-wrapper').toggleClass('form-disabled', e.value)
+        .find(':input').attr('disabled', e.value);
+
+      // Note: WebKit nightlies don't reflect that change correctly.
+      // See https://bugs.webkit.org/show_bug.cgi?id=23789
+    }
+  });
+})(jQuery);

+ 15 - 0
mydata/themes/bootstrap/js/misc/tabledrag.js

@@ -0,0 +1,15 @@
+(function ($) {
+
+  /**
+   * Add an asterisk or other marker to the changed row.
+   */
+  Drupal.tableDrag.prototype.row.prototype.markChanged = function () {
+    var $cell = $('td:first', this.element);
+    // Find the first appropriate place to insert the marker.
+    var $target = $($cell.find('.file-size').get(0) || $cell.find('.file').get(0) || $cell.find('.tabledrag-handle').get(0));
+    if (!$cell.find('.tabledrag-changed').length) {
+      $target.after(' ' + Drupal.theme('tableDragChangedMarker') + ' ');
+    }
+  };
+
+})(jQuery);

+ 32 - 0
mydata/themes/bootstrap/js/modules/comment/_comment-node-form.js

@@ -0,0 +1,32 @@
+
+(function ($) {
+
+Drupal.behaviors.commentFieldsetSummaries = {
+  attach: function (context) {
+    $('.comment-node-settings-form', context).drupalSetSummary(function (context) {
+      return Drupal.checkPlain($('.form-item-comment input:checked', context).closest('label').text());
+    });
+
+    // Provide the summary for the node type form.
+    $('.comment-node-type-settings-form', context).drupalSetSummary(function(context) {
+      var vals = [];
+
+      // Default comment setting.
+      vals.push($(".form-item-comment select option:selected", context).text());
+
+      // Threading.
+      var threading = $(".form-item-comment-default-mode input:checked", context).closest('label').text();
+      if (threading) {
+        vals.push(threading);
+      }
+
+      // Comments per page.
+      var number = $(".form-item-comment-default-per-page select option:selected", context).val();
+      vals.push(Drupal.t('@number comments per page', {'@number': number}));
+
+      return Drupal.checkPlain(vals.join(', '));
+    });
+  }
+};
+
+})(jQuery);

+ 150 - 0
mydata/themes/bootstrap/js/modules/ctools/js/modal.js

@@ -0,0 +1,150 @@
+/**
+ * @file
+ *
+ * Overrides for ctools modal.
+ *
+ */
+
+(function ($) {
+  /**
+   * Override CTools modal show function so it can recognize the Bootstrap modal classes correctly
+   */
+  Drupal.CTools.Modal.show = function(choice) {
+    var opts = {};
+
+    if (choice && typeof choice === 'string' && Drupal.settings[choice]) {
+      // This notation guarantees we are actually copying it.
+      $.extend(true, opts, Drupal.settings[choice]);
+    }
+    else if (choice) {
+      $.extend(true, opts, choice);
+    }
+
+    var defaults = {
+      modalTheme: 'CToolsModalDialog',
+      throbberTheme: 'CToolsModalThrobber',
+      animation: 'show',
+      animationSpeed: 'fast',
+      modalSize: {
+        type: 'scale',
+        width: 0.8,
+        height: 0.8,
+        addWidth: 0,
+        addHeight: 0,
+        // How much to remove from the inner content to make space for the
+        // theming.
+        contentRight: 25,
+        contentBottom: 45
+      },
+      modalOptions: {
+        opacity: 0.55,
+        background: '#fff'
+      },
+      modalClass: 'default'
+    };
+
+    var settings = {};
+    $.extend(true, settings, defaults, Drupal.settings.CToolsModal, opts);
+
+    if (Drupal.CTools.Modal.currentSettings && Drupal.CTools.Modal.currentSettings !== settings) {
+      Drupal.CTools.Modal.modal.remove();
+      Drupal.CTools.Modal.modal = null;
+    }
+
+    Drupal.CTools.Modal.currentSettings = settings;
+
+    var resize = function(e) {
+      // When creating the modal, it actually exists only in a theoretical
+      // place that is not in the DOM. But once the modal exists, it is in the
+      // DOM so the context must be set appropriately.
+      var context = e ? document : Drupal.CTools.Modal.modal;
+      var width = 0;
+      var height = 0;
+
+      //  Handle fixed navbars. Grab the body top offset in pixels.
+      var topOffset = parseInt($('body').css("padding-top"), 10);
+
+      if (Drupal.CTools.Modal.currentSettings.modalSize.type === 'scale') {
+        width = $(window).width() * Drupal.CTools.Modal.currentSettings.modalSize.width;
+        height = ($(window).height() - topOffset) * Drupal.CTools.Modal.currentSettings.modalSize.height;
+      }
+      else {
+        width = Drupal.CTools.Modal.currentSettings.modalSize.width;
+        height = Drupal.CTools.Modal.currentSettings.modalSize.height;
+      }
+
+      // Add padding for the offset.
+      $('#modalContent').css('padding-top', topOffset + 'px');
+
+      // Use the additionol pixels for creating the width and height.
+      $('div.ctools-modal-dialog', context).css({
+        'width': width + Drupal.CTools.Modal.currentSettings.modalSize.addWidth + 'px',
+        'height': height + Drupal.CTools.Modal.currentSettings.modalSize.addHeight + 'px'
+      });
+
+      $('div.ctools-modal-dialog .modal-body', context).css({
+        'width': (width - Drupal.CTools.Modal.currentSettings.modalSize.contentRight) + 'px',
+        'max-height': (height - Drupal.CTools.Modal.currentSettings.modalSize.contentBottom) + 'px'
+      });
+    };
+
+    if (!Drupal.CTools.Modal.modal) {
+      Drupal.CTools.Modal.modal = $(Drupal.theme(settings.modalTheme));
+      if (settings.modalSize.type === 'scale') {
+        $(window).bind('resize', resize);
+      }
+    }
+
+    $('body').addClass('modal-open');
+
+    resize();
+
+    $('.modal-title', Drupal.CTools.Modal.modal).html(Drupal.CTools.Modal.currentSettings.loadingText);
+    Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed, settings.modalClass);
+    $('#modalContent .modal-body').html(Drupal.theme(settings.throbberTheme)).addClass('ctools-modal-loading');
+  };
+
+  /**
+   * Remove modal class from body when closing modal.
+   */
+  $(document).on('CToolsDetachBehaviors', function() {
+    $('body').removeClass('modal-open');
+  });
+
+  /**
+   * Provide the HTML to create the modal dialog in the Bootstrap style.
+   */
+  Drupal.theme.prototype.CToolsModalDialog = function () {
+    var html = '';
+    html += '<div id="ctools-modal">';
+    html += '  <div class="ctools-modal-dialog modal-dialog">';
+    html += '    <div class="modal-content">';
+    html += '      <div class="modal-header">';
+    html += '        <button type="button" class="close ctools-close-modal" aria-hidden="true">&times;</button>';
+    html += '        <h4 id="modal-title" class="modal-title">&nbsp;</h4>';
+    html += '      </div>';
+    html += '      <div id="modal-content" class="modal-body">';
+    html += '      </div>';
+    html += '    </div>';
+    html += '  </div>';
+    html += '</div>';
+
+    return html;
+  };
+
+  /**
+   * Provide the HTML to create a nice looking loading progress bar.
+   */
+  Drupal.theme.prototype.CToolsModalThrobber = function () {
+    var html = '';
+    html += '<div class="loading-spinner" style="width: 200px; margin: -20px 0 0 -100px; position: absolute; top: 45%; left: 50%">';
+    html += '  <div class="progress progress-striped active">';
+    html += '    <div class="progress-bar" style="width: 100%;"></div>';
+    html += '  </div>';
+    html += '</div>';
+
+    return html;
+  };
+
+
+})(jQuery);

+ 27 - 0
mydata/themes/bootstrap/js/modules/dashboard/dashboard.js

@@ -0,0 +1,27 @@
+(function ($) {
+  // Override core JS so it works with "button" tags.
+  if (Drupal.behaviors.dashboard && Drupal.behaviors.dashboard.setupDrawer) {
+    /**
+     * Sets up the drag-and-drop behavior and the 'close' button.
+     */
+    Drupal.behaviors.dashboard.setupDrawer = function () {
+      $('div.customize .canvas-content :input').click(Drupal.behaviors.dashboard.exitCustomizeMode);
+      $('div.customize .canvas-content').append('<a class="button" href="' + Drupal.settings.dashboard.dashboard + '">' + Drupal.t('Done') + '</a>');
+      // Initialize drag-and-drop.
+      var regions = $('#dashboard div.region');
+      regions.sortable({
+        connectWith: regions,
+        cursor: 'move',
+        cursorAt: {top:0},
+        dropOnEmpty: true,
+        items: '> div.block, > div.disabled-block',
+        placeholder: 'block-placeholder clearfix',
+        tolerance: 'pointer',
+        start: Drupal.behaviors.dashboard.start,
+        over: Drupal.behaviors.dashboard.over,
+        sort: Drupal.behaviors.dashboard.sort,
+        update: Drupal.behaviors.dashboard.update
+      });
+    };
+  }
+})(jQuery);

+ 43 - 0
mydata/themes/bootstrap/js/modules/field_ui/field_ui.js

@@ -0,0 +1,43 @@
+(function ($) {
+  // Override core JS so it works with "button" tags.
+  if (Drupal.fieldUIOverview && Drupal.fieldUIOverview.AJAXRefreshRows) {
+    /**
+     * Triggers Ajax refresh of selected rows.
+     *
+     * The 'format type' selects can trigger a series of changes in child rows.
+     * The #ajax behavior is therefore not attached directly to the selects, but
+     * triggered manually through a hidden #ajax 'Refresh' button.
+     *
+     * @param rows
+     *   A hash object, whose keys are the names of the rows to refresh (they
+     *   will receive the 'ajax-new-content' effect on the server side), and
+     *   whose values are the DOM element in the row that should get an Ajax
+     *   throbber.
+     */
+    Drupal.fieldUIOverview.AJAXRefreshRows = function (rows) {
+      // Separate keys and values.
+      var rowNames = [];
+      var ajaxElements = [];
+      $.each(rows, function (rowName, ajaxElement) {
+        rowNames.push(rowName);
+        ajaxElements.push(ajaxElement);
+      });
+
+      if (rowNames.length) {
+        // Add a throbber next each of the ajaxElements.
+        var $throbber = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
+        $(ajaxElements)
+          .addClass('progress-disabled')
+          .after($throbber);
+
+        // Fire the Ajax update.
+        $(':input[name=refresh_rows]').val(rowNames.join(' '));
+        $(':input#edit-refresh').mousedown();
+
+        // Disabled elements do not appear in POST ajax data, so we mark the
+        // elements disabled only after firing the request.
+        $(ajaxElements).attr('disabled', true);
+      }
+    };
+  }
+})(jQuery);

+ 105 - 0
mydata/themes/bootstrap/js/modules/file/file.js

@@ -0,0 +1,105 @@
+(function ($) {
+  // Override core JS so it works with "button" tags.
+  /**
+   * Attach behaviors to the file upload and remove buttons.
+   */
+  Drupal.behaviors.fileButtons = {
+    attach: function (context) {
+      $(':input.form-submit', context).bind('mousedown', Drupal.file.disableFields);
+      $('div.form-managed-file :input.form-submit', context).bind('mousedown', Drupal.file.progressBar);
+    },
+    detach: function (context) {
+      $(':input.form-submit', context).unbind('mousedown', Drupal.file.disableFields);
+      $('div.form-managed-file :input.form-submit', context).unbind('mousedown', Drupal.file.progressBar);
+    }
+  };
+  if (Drupal.file) {
+    /**
+     * Prevent file uploads when using buttons not intended to upload.
+     */
+    Drupal.file.disableFields = function (event){
+      var clickedButton = this;
+
+      // Only disable upload fields for Ajax buttons.
+      if (!$(clickedButton).hasClass('ajax-processed')) {
+        return;
+      }
+
+      // Check if we're working with an "Upload" button.
+      var $enabledFields = [];
+      if ($(this).closest('div.form-managed-file').length > 0) {
+        $enabledFields = $(this).closest('div.form-managed-file').find(':input.form-file');
+      }
+
+      // Temporarily disable upload fields other than the one we're currently
+      // working with. Filter out fields that are already disabled so that they
+      // do not get enabled when we re-enable these fields at the end of behavior
+      // processing. Re-enable in a setTimeout set to a relatively short amount
+      // of time (1 second). All the other mousedown handlers (like Drupal's Ajax
+      // behaviors) are excuted before any timeout functions are called, so we
+      // don't have to worry about the fields being re-enabled too soon.
+      // @todo If the previous sentence is true, why not set the timeout to 0?
+      var $fieldsToTemporarilyDisable = $('div.form-managed-file :input.form-file').not($enabledFields).not(':disabled');
+      $fieldsToTemporarilyDisable.attr('disabled', 'disabled');
+      setTimeout(function (){
+        $fieldsToTemporarilyDisable.attr('disabled', false);
+      }, 1000);
+    };
+    /**
+     * Add progress bar support if possible.
+     */
+    Drupal.file.progressBar = function (event) {
+      var clickedButton = this;
+      var $progressId = $(clickedButton).closest('div.form-managed-file').find(':input.file-progress');
+      if ($progressId.length) {
+        var originalName = $progressId.attr('name');
+
+        // Replace the name with the required identifier.
+        $progressId.attr('name', originalName.match(/APC_UPLOAD_PROGRESS|UPLOAD_IDENTIFIER/)[0]);
+
+        // Restore the original name after the upload begins.
+        setTimeout(function () {
+          $progressId.attr('name', originalName);
+        }, 1000);
+      }
+      // Show the progress bar if the upload takes longer than half a second.
+      setTimeout(function () {
+        $(clickedButton).closest('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
+      }, 500);
+    };
+
+    /**
+     * Styling invalid file extension error message (Issue #2331595 by NetTantra).
+     */
+    Drupal.file.validateExtension = function (event) {
+      // Remove any previous errors.
+      $('.file-upload-js-error').remove();
+
+      // Add client side validation for the input[type=file].
+      var extensionPattern = event.data.extensions.replace(/,\s*/g, '|');
+      if (extensionPattern.length > 1 && this.value.length > 0) {
+        var acceptableMatch = new RegExp('\\.(' + extensionPattern + ')$', 'gi');
+        if (!acceptableMatch.test(this.value)) {
+          var error = Drupal.t("The selected file %filename cannot be uploaded. Only files with the following extensions are allowed: %extensions.", {
+            // According to the specifications of HTML5, a file upload control
+            // should not reveal the real local path to the file that a user
+            // has selected. Some web browsers implement this restriction by
+            // replacing the local path with "C:\fakepath\", which can cause
+            // confusion by leaving the user thinking perhaps Drupal could not
+            // find the file because it messed up the file path. To avoid this
+            // confusion, therefore, we strip out the bogus fakepath string.
+            '%filename': this.value.replace('C:\\fakepath\\', ''),
+            '%extensions': extensionPattern.replace(/\|/g, ', ')
+          });
+          $(this).closest('div.form-managed-file').parents('.form-item').first().prepend('<div class="alert alert-danger alert-dismissible messages error file-upload-js-error" aria-live="polite" role="alert">\
+            <button type="button" class="close" data-dismiss="alert">\
+              <span aria-hidden="true">&times;</span>\
+              <span class="sr-only">Close</span>\
+            </button>' + error + '</div>');
+          this.value = '';
+          return false;
+        }
+      }
+    };
+  }
+})(jQuery);

+ 24 - 0
mydata/themes/bootstrap/js/modules/filter/filter.js

@@ -0,0 +1,24 @@
+(function ($) {
+
+  function updateFilterHelpLink () {
+    var $link = $(this).parents('.filter-wrapper').find('.filter-help > a');
+    var originalLink = $link.data('originalLink');
+    if (!originalLink) {
+      originalLink = $link.attr('href');
+      $link.data('originalLink', originalLink);
+    }
+    $link.attr('href', originalLink + '/' + $(this).find(':selected').val());
+  }
+
+  $(document).on('change', '.filter-wrapper select.filter-list', updateFilterHelpLink);
+
+  /**
+   * Override core's functionality.
+   */
+  Drupal.behaviors.filterGuidelines = {
+    attach: function (context) {
+      $(context).find('.filter-wrapper select.filter-list').once('filter-list', updateFilterHelpLink);
+    }
+  };
+
+})(jQuery);

+ 162 - 0
mydata/themes/bootstrap/js/modules/user/user.js

@@ -0,0 +1,162 @@
+(function ($, Drupal) {
+
+  Drupal.BootstrapPassword = function (element) {
+    var self = this;
+    var $element = $(element);
+    this.settings = Drupal.settings.password;
+    this.$wrapper = $element.parent().parent();
+    this.$row = $('<div class="row">').prependTo(this.$wrapper);
+
+    // The password object.
+    this.password = {
+      $input: $element,
+      $label: $element.parent().find('label'),
+      $wrapper: $element.parent().addClass('col-sm-6 col-md-4 has-feedback').appendTo(self.$row)
+    };
+    this.password.$icon = $('<span class="glyphicon form-control-feedback"></span>').appendTo(this.password.$wrapper);
+
+    // Strength meter.
+    this.strength = {
+      $label: $('<div class="label" aria-live="assertive"></div>').appendTo(this.password.$label),
+      $progress: $('<div class="progress"><div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div></div>').appendTo(this.password.$wrapper)
+    };
+    this.strength.$bar = this.strength.$progress.find('.progress-bar');
+
+    // The confirmation object.
+    this.confirm = {
+      $input: this.$wrapper.find('input.password-confirm')
+    };
+    this.confirm.$wrapper = this.confirm.$input.parent().addClass('col-sm-6 col-md-4 has-feedback').appendTo(self.$row);
+    this.confirm.$icon = $('<span class="glyphicon form-control-feedback"></span>').appendTo(this.confirm.$wrapper);
+
+    // Bind events.
+    this.password.$input.on('keyup focus blur', function () {
+      self.validateStrength();
+    });
+    this.confirm.$input.on('keyup blur', function () {
+      self.validateMatch();
+    });
+
+    // Add password help at the of row.
+    this.$helpBlock = $('<div class="help-block password-help"></div>').appendTo(this.$row);
+
+    return this;
+  };
+
+  /**
+   * Helper method to switch classes on elements based on status.
+   *
+   * @param {jQuery} $element
+   *   The jQuery element to modify.
+   * @param {string} type
+   *   The name of the class to switch to. Can be one of: "danger", "info",
+   *   "success" or "warning".
+   * @param {string} prefix
+   *   The prefix to use. Typically this would be something like "label" or
+   *   "progress-bar".
+   */
+  Drupal.BootstrapPassword.prototype.switchClass = function ($element, type, prefix) {
+    prefix = prefix + '-' || '';
+    var types = prefix === 'has-' ? ['error', 'warning', 'success'] : ['danger', 'info', 'success', 'warning'];
+    if (type) {
+      type = types.splice($.inArray(type, types), 1).shift();
+      $element.addClass(prefix + type);
+    }
+    $element.removeClass(prefix + types.join(' ' + prefix));
+  };
+
+  /**
+   * Validates the strength of a password.
+   */
+  Drupal.BootstrapPassword.prototype.validateStrength = function () {
+    var result = Drupal.evaluatePasswordStrength(this.password.$input.val(), Drupal.settings.password);
+
+    // Ensure visibility.
+    this.$helpBlock.show();
+    this.strength.$label.show();
+    this.strength.$bar.show();
+
+    // Update the suggestions for how to improve the password.
+    this.$helpBlock.html(result.message);
+
+    // Only show the description box if there is a weakness in the password.
+    this.$helpBlock[result.strength === 100 ? 'hide' : 'show']();
+
+    // Update the strength indication text.
+    this.strength.$label.html(result.indicatorText);
+
+    // Adjust the length of the strength indicator.
+    this.strength.$bar.attr('aria-valuenow', result.strength);
+    this.strength.$bar.css('width', result.strength + '%');
+
+    // Change the classes (color) of the strength meter based on result level.
+    switch (result.indicatorText) {
+      case this.settings.weak:
+        this.switchClass(this.password.$wrapper, 'error', 'has');
+        this.switchClass(this.strength.$label, 'danger', 'label');
+        this.switchClass(this.strength.$bar, 'danger', 'progress-bar');
+        this.password.$icon.addClass('glyphicon-remove').removeClass('glyphicon-warning-sign glyphicon-ok');
+        break;
+
+      case this.settings.fair:
+      case this.settings.good:
+        this.switchClass(this.password.$wrapper, 'warning', 'has');
+        this.switchClass(this.strength.$label, 'warning', 'label');
+        this.switchClass(this.strength.$bar, 'warning', 'progress-bar');
+        this.password.$icon.addClass('glyphicon-warning-sign').removeClass('glyphicon-remove glyphicon-ok');
+        break;
+
+      case this.settings.strong:
+        this.switchClass(this.password.$wrapper, 'success', 'has');
+        this.switchClass(this.strength.$label, 'success', 'label');
+        this.switchClass(this.strength.$bar, 'success', 'progress-bar');
+        this.password.$icon.addClass('glyphicon-ok').removeClass('glyphicon-warning-sign glyphicon-remove');
+        break;
+    }
+    this.validateMatch();
+  };
+
+  /**
+   * Validates both original and confirmation passwords to ensure they match.
+   */
+  Drupal.BootstrapPassword.prototype.validateMatch = function () {
+    var password = this.password.$input.val();
+
+    // Passwords match.
+    if (password && password === this.confirm.$input.val()) {
+      this.switchClass(this.password.$wrapper, 'success', 'has');
+      this.switchClass(this.confirm.$wrapper, 'success', 'has');
+      this.$helpBlock.hide();
+      this.strength.$label.hide();
+      this.strength.$bar.hide();
+      this.password.$icon.addClass('glyphicon-ok').removeClass('glyphicon-warning-sign glyphicon-remove');
+      this.confirm.$icon.addClass('glyphicon-ok').removeClass('glyphicon-remove');
+    }
+    // Passwords do not match.
+    else if (password) {
+      this.switchClass(this.confirm.$wrapper, 'error', 'has');
+      this.confirm.$icon.addClass('glyphicon-remove').removeClass('glyphicon-ok');
+    }
+    // No password.
+    else {
+      this.confirm.$icon.removeClass('glyphicon-ok glyphicon-remove');
+      this.confirm.$input.val('');
+      this.switchClass(this.confirm.$wrapper, '', 'has');
+    }
+  };
+
+  /**
+   * Overrides core JS for password strength and confirmation.
+   *
+   * Attach handlers to evaluate the strength of any password fields and to check
+   * that its confirmation is correct.
+   */
+  Drupal.behaviors.password = {
+    attach: function (context) {
+      $('input.password-field', context).once('password', function () {
+        new Drupal.BootstrapPassword(this);
+      });
+    }
+  };
+
+})(jQuery, window.Drupal);

+ 12 - 0
mydata/themes/bootstrap/js/modules/views/js/ajax_view.js

@@ -0,0 +1,12 @@
+(function ($) {
+
+/**
+ * Override Views prototype function so it can recognize Bootstrap AJAX pagers.
+ * Attach the ajax behavior to each link.
+ */
+Drupal.views.ajaxView.prototype.attachPagerAjax = function() {
+  this.$view.find('ul.pager > li > a, th.views-field a, .attachment .views-summary a, ul.pagination li a')
+  .each(jQuery.proxy(this.attachPagerLinkAjax, this));
+};
+
+})(jQuery);

BIN
mydata/themes/bootstrap/logo.png


BIN
mydata/themes/bootstrap/screenshot.png


+ 70 - 0
mydata/themes/bootstrap/starterkits/THEMENAME/THEMENAME.starterkit

@@ -0,0 +1,70 @@
+name = 'THEMETITLE'
+description = 'A Drupal Bootstrap 3 based sub-theme.'
+core = 7.x
+base theme = bootstrap
+php = 5.3.0
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Regions
+;;;;;;;;;;;;;;;;;;;;;
+
+regions[navigation]     = 'Navigation'
+regions[header]         = 'Top Bar'
+regions[highlighted]    = 'Highlighted'
+regions[help]           = 'Help'
+regions[content]        = 'Content'
+regions[sidebar_first]  = 'Primary'
+regions[sidebar_second] = 'Secondary'
+regions[footer]         = 'Footer'
+regions[page_top]       = 'Page top'
+regions[page_bottom]    = 'Page bottom'
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Stylesheets
+;;;;;;;;;;;;;;;;;;;;;
+
+stylesheets[all][] = css/style.css
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Scripts
+;;;;;;;;;;;;;;;;;;;;;
+
+; Uncomment the following scripts if using Less source JavaScript files.
+;scripts[] = 'bootstrap/js/affix.js'
+;scripts[] = 'bootstrap/js/alert.js'
+;scripts[] = 'bootstrap/js/button.js'
+;scripts[] = 'bootstrap/js/carousel.js'
+;scripts[] = 'bootstrap/js/collapse.js'
+;scripts[] = 'bootstrap/js/dropdown.js'
+;scripts[] = 'bootstrap/js/modal.js'
+;scripts[] = 'bootstrap/js/tooltip.js'
+;scripts[] = 'bootstrap/js/popover.js'
+;scripts[] = 'bootstrap/js/scrollspy.js'
+;scripts[] = 'bootstrap/js/tab.js'
+;scripts[] = 'bootstrap/js/transition.js'
+
+; Uncomment the following scripts if using Sass source JavaScript files.
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/affix.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/alert.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/button.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/carousel.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/collapse.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/dropdown.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/modal.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/tooltip.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/popover.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/scrollspy.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/tab.js'
+;scripts[] = 'bootstrap/assets/javascripts/bootstrap/transition.js'
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Theme Settings
+;;;;;;;;;;;;;;;;;;;;;
+
+; Uncomment if using Sass or Less source files. This disables the CDN provider
+; so compiled source files can be used instead.
+;settings[bootstrap_cdn_provider] = ''

+ 4 - 0
mydata/themes/bootstrap/starterkits/THEMENAME/css/style.css

@@ -0,0 +1,4 @@
+/**
+ * If using a CSS pre-processor, tell it to overwrite this file. If not, place
+ * your custom CSS modifications here.
+ */

BIN
mydata/themes/bootstrap/starterkits/THEMENAME/favicon.ico


BIN
mydata/themes/bootstrap/starterkits/THEMENAME/logo.png


BIN
mydata/themes/bootstrap/starterkits/THEMENAME/screenshot.png


+ 8 - 0
mydata/themes/bootstrap/starterkits/THEMENAME/template.php

@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * @file
+ * Bootstrap sub-theme.
+ *
+ * Place your custom PHP code in this file.
+ */

+ 4 - 0
mydata/themes/bootstrap/starterkits/THEMENAME/templates/README.md

@@ -0,0 +1,4 @@
+This directory is used to implement various core, contrib, Bootstrap and custom
+templates as well as theme and \[pre\]process functions.
+
+Please refer to the [Theme Registry](<!-- @url registry -->) topic for more info.

+ 69 - 0
mydata/themes/bootstrap/template.php

@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * The primary PHP file for the Drupal Bootstrap base theme.
+ *
+ * This file should only contain light helper functions and point to stubs in
+ * other files containing more complex functions.
+ *
+ * The stubs should point to files within the `./includes` folder named after
+ * the function itself minus the theme prefix. If the stub contains a group of
+ * functions, then please organize them so they are related in some way and name
+ * the file appropriately to at least hint at what it contains.
+ *
+ * All [pre]process functions, theme functions and template files lives inside
+ * the `./templates` folder. This is a highly automated and complex system
+ * designed to only load the necessary files when a given theme hook is invoked.
+ *
+ * Visit this project's official documentation site https://drupal-bootstrap.org
+ * or the markdown files inside the `./docs` folder.
+ *
+ * @see _bootstrap_theme()
+ */
+
+/**
+ * Include common functions used through out theme.
+ */
+include_once dirname(__FILE__) . '/includes/common.inc';
+
+/**
+ * Include any deprecated functions.
+ */
+bootstrap_include('bootstrap', 'includes/deprecated.inc');
+
+/**
+ * Implements hook_theme().
+ *
+ * Register theme hook implementations.
+ *
+ * The implementations declared by this hook have two purposes: either they
+ * specify how a particular render array is to be rendered as HTML (this is
+ * usually the case if the theme function is assigned to the render array's
+ * #theme property), or they return the HTML that should be returned by an
+ * invocation of theme().
+ *
+ * @see _bootstrap_theme()
+ */
+function bootstrap_theme(&$existing, $type, $theme, $path) {
+  bootstrap_include($theme, 'includes/registry.inc');
+  return _bootstrap_theme($existing, $type, $theme, $path);
+}
+
+/**
+ * Clear any previously set element_info() static cache.
+ *
+ * If element_info() was invoked before the theme was fully initialized, this
+ * can cause the theme's alter hook to not be invoked.
+ *
+ * @see https://www.drupal.org/node/2351731
+ */
+drupal_static_reset('element_info');
+
+/**
+ * Declare various hook_*_alter() hooks.
+ *
+ * All hook_*_alter() implementations must live (via include) inside this file
+ * so they are properly detected when drupal_alter() is invoked.
+ */
+bootstrap_include('bootstrap', 'includes/alter.inc');

+ 32 - 0
mydata/themes/bootstrap/templates/admin_menu/admin-menu-links.vars.php

@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "admin_menu_links" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "admin_menu_links" theme hook.
+ *
+ * @param array $variables
+ *   - elements: A renderable array of links using the following keys:
+ *     - #attributes: Optional array of attributes for the list item, processed
+ *       via drupal_attributes().
+ *     - #title: Title of the link, passed to l().
+ *     - #href: Optional path of the link, passed to l(). When omitted, the
+ *       element's '#title' is rendered without link.
+ *     - #description: Optional alternative text for the link, passed to l().
+ *     - #options: Optional alternative text for the link, passed to l().
+ *     The array key of each child element itself is passed as path for l().
+ *
+ * @see theme_admin_menu_links()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_admin_menu_links(array &$variables) {
+  $elements = &$variables['elements'];
+  foreach (element_children($elements) as $child) {
+    $elements[$child]['#bootstrap_ignore_pre_render'] = TRUE;
+    $elements[$child]['#bootstrap_ignore_process'] = TRUE;
+  }
+}

+ 69 - 0
mydata/themes/bootstrap/templates/block/block-admin-display-form.tpl.php

@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to configure blocks.
+ *
+ * Available variables:
+ * - $block_regions: An array of regions. Keyed by name with the title as value.
+ * - $block_listing: An array of blocks keyed by region and then delta.
+ * - $form_submit: Form submit button.
+ *
+ * Each $block_listing[$region] contains an array of blocks for that region.
+ *
+ * Each $data in $block_listing[$region] contains:
+ * - $data->region_title: Region title for the listed block.
+ * - $data->block_title: Block title.
+ * - $data->region_select: Drop-down menu for assigning a region.
+ * - $data->weight_select: Drop-down menu for setting weights.
+ * - $data->configure_link: Block configuration link.
+ * - $data->delete_link: For deleting user added blocks.
+ *
+ * @see template_preprocess_block_admin_display_form()
+ * @see theme_block_admin_display()
+ *
+ * @ingroup templates
+ */
+?>
+<?php
+  // Add table javascript.
+  drupal_add_js('misc/tableheader.js');
+  drupal_add_js(drupal_get_path('module', 'block') . '/block.js');
+  foreach ($block_regions as $region => $title):
+    drupal_add_tabledrag('blocks', 'match', 'sibling', 'block-region-select', 'block-region-' . $region, NULL, FALSE);
+    drupal_add_tabledrag('blocks', 'order', 'sibling', 'block-weight', 'block-weight-' . $region);
+  endforeach;
+?>
+<table id="blocks" class="table table-hover sticky-enabled">
+  <thead>
+    <tr>
+      <th><?php print t('Block'); ?></th>
+      <th><?php print t('Region'); ?></th>
+      <th><?php print t('Weight'); ?></th>
+      <th colspan="2"><?php print t('Operations'); ?></th>
+    </tr>
+  </thead>
+  <tbody>
+    <?php $row = 0; ?>
+    <?php foreach ($block_regions as $region => $title): ?>
+      <tr class="active region-title region-title-<?php print $region?>">
+        <td colspan="5"><?php print $title; ?></td>
+      </tr>
+      <tr class="region-message region-<?php print $region?>-message <?php print empty($block_listing[$region]) ? 'region-empty' : 'region-populated'; ?>">
+        <td colspan="5"><em><?php print t('No blocks in this region'); ?></em></td>
+      </tr>
+      <?php foreach ($block_listing[$region] as $delta => $data): ?>
+      <tr class="draggable <?php print $row % 2 == 0 ? 'odd' : 'even'; ?><?php print $data->row_class ? ' ' . $data->row_class : ''; ?>">
+        <td class="block"><?php print $data->block_title; ?></td>
+        <td><?php print $data->region_select; ?></td>
+        <td><?php print $data->weight_select; ?></td>
+        <td><?php print $data->configure_link; ?></td>
+        <td><?php print $data->delete_link; ?></td>
+      </tr>
+      <?php $row++; ?>
+      <?php endforeach; ?>
+    <?php endforeach; ?>
+  </tbody>
+</table>
+
+<?php print $form_submit; ?>

+ 59 - 0
mydata/themes/bootstrap/templates/block/block.tpl.php

@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display a block.
+ *
+ * Available variables:
+ * - $block->subject: Block title.
+ * - $content: Block content.
+ * - $block->module: Module that generated the block.
+ * - $block->delta: An ID for the block, unique within each module.
+ * - $block->region: The block region embedding the current block.
+ * - $classes: String of classes that can be used to style contextually through
+ *   CSS. It can be manipulated through the variable $classes_array from
+ *   preprocess functions. The default values can be one or more of the
+ *   following:
+ *   - block: The current template type, i.e., "theming hook".
+ *   - block-[module]: The module generating the block. For example, the user
+ *     module is responsible for handling the default user navigation block. In
+ *     that case the class would be 'block-user'.
+ * - $title_prefix (array): An array containing additional output populated by
+ *   modules, intended to be displayed in front of the main title tag that
+ *   appears in the template.
+ * - $title_suffix (array): An array containing additional output populated by
+ *   modules, intended to be displayed after the main title tag that appears in
+ *   the template.
+ *
+ * Helper variables:
+ * - $classes_array: Array of html class attribute values. It is flattened
+ *   into a string within the variable $classes.
+ * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region.
+ * - $zebra: Same output as $block_zebra but independent of any block region.
+ * - $block_id: Counter dependent on each block region.
+ * - $id: Same output as $block_id but independent of any block region.
+ * - $is_front: Flags true when presented in the front page.
+ * - $logged_in: Flags true when the current user is a logged-in member.
+ * - $is_admin: Flags true when the current user is an administrator.
+ * - $block_html_id: A valid HTML ID and guaranteed unique.
+ *
+ * @see bootstrap_preprocess_block()
+ * @see template_preprocess()
+ * @see template_preprocess_block()
+ * @see bootstrap_process_block()
+ * @see template_process()
+ *
+ * @ingroup templates
+ */
+?>
+<section id="<?php print $block_html_id; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
+
+  <?php print render($title_prefix); ?>
+  <?php if ($title): ?>
+    <h2<?php print $title_attributes; ?>><?php print $title; ?></h2>
+  <?php endif;?>
+  <?php print render($title_suffix); ?>
+
+  <?php print $content ?>
+
+</section>

+ 47 - 0
mydata/themes/bootstrap/templates/block/block.vars.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "block" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "block" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see block.tpl.php
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_block(array &$variables) {
+  // Use a bare template for the page's main content.
+  if ($variables['block_html_id'] == 'block-system-main') {
+    $variables['theme_hook_suggestions'][] = 'block__no_wrapper';
+  }
+  $variables['title_attributes_array']['class'][] = 'block-title';
+}
+
+/**
+ * Processes variables for the "block" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see block.tpl.php
+ *
+ * @ingroup theme_process
+ */
+function bootstrap_process_block(array &$variables) {
+  // Drupal 7 should use a $title variable instead of $block->subject.
+  // Don't override an existing "title" variable, some modules may already it.
+  if (!isset($variables['title'])) {
+    $variables['title'] = $variables['block']->subject;
+  }
+  $variables['title'] = filter_xss_admin($variables['title']);
+}

+ 54 - 0
mydata/themes/bootstrap/templates/book/book-navigation.tpl.php

@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to navigate books.
+ *
+ * Presented under nodes that are a part of book outlines.
+ *
+ * Available variables:
+ * - $tree: The immediate children of the current node rendered as an unordered
+ *   list.
+ * - $current_depth: Depth of the current node within the book outline. Provided
+ *   for context.
+ * - $prev_url: URL to the previous node.
+ * - $prev_title: Title of the previous node.
+ * - $parent_url: URL to the parent node.
+ * - $parent_title: Title of the parent node. Not printed by default. Provided
+ *   as an option.
+ * - $next_url: URL to the next node.
+ * - $next_title: Title of the next node.
+ * - $has_links: Flags TRUE whenever the previous, parent or next data has a
+ *   value.
+ * - $book_id: The book ID of the current outline being viewed. Same as the node
+ *   ID containing the entire outline. Provided for context.
+ * - $book_url: The book/node URL of the current outline being viewed. Provided
+ *   as an option. Not used by default.
+ * - $book_title: The book/node title of the current outline being viewed.
+ *   Provided as an option. Not used by default.
+ *
+ * @see template_preprocess_book_navigation()
+ *
+ * @ingroup templates
+ */
+?>
+<?php if ($tree || $has_links): ?>
+  <div id="book-navigation-<?php print $book_id; ?>" class="book-navigation">
+    <?php print $tree; ?>
+
+    <?php if ($has_links): ?>
+    <ul class="pager clearfix">
+      <?php if ($prev_url): ?>
+        <li class="previous"><a href="<?php print $prev_url; ?>" class="page-previous" title="<?php print t('Go to previous page'); ?>"><?php print t('‹ @label', array('@label' => $prev_title)); ?></a></li>
+      <?php endif; ?>
+      <?php if ($parent_url): ?>
+        <li><a href="<?php print $parent_url; ?>" class="page-up" title="<?php print t('Go to parent page'); ?>"><?php print t('up'); ?></a></li>
+      <?php endif; ?>
+      <?php if ($next_url): ?>
+        <li class="next"><a href="<?php print $next_url; ?>" class="page-next" title="<?php print t('Go to next page'); ?>"><?php print t('@label ›', array('@label' => $next_title)); ?></a></li>
+      <?php endif; ?>
+    </ul>
+    <?php endif; ?>
+
+  </div>
+<?php endif; ?>

+ 65 - 0
mydata/themes/bootstrap/templates/book/book-navigation.vars.php

@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "book_navigation" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "book_navigation" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see book-navigation.tpl.php
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_book_navigation(array &$variables) {
+  $variables['tree'] = _bootstrap_book_children($variables['book_link']);
+}
+
+/**
+ * Formats the menu links for the child pages of the current page.
+ *
+ * @param array $book_link
+ *   A fully loaded menu link that is part of the book hierarchy.
+ *
+ * @return string
+ *   HTML for the links to the child pages of the current page.
+ */
+function _bootstrap_book_children(array $book_link) {
+  // Rebuild entire menu tree for the book.
+  $tree = menu_build_tree($book_link['menu_name']);
+  $tree = menu_tree_output($tree);
+
+  // Fix the theme hook suggestions.
+  _bootstrap_book_fix_theme_hooks($book_link['nid'], $tree);
+
+  // Return the rendered output.
+  return drupal_render($tree);
+}
+
+/**
+ * Helper function to fix theme hooks in book TOC menus.
+ *
+ * @param int $bid
+ *   The book identification number.
+ * @param array $element
+ *   The element to iterate over, passed by reference.
+ * @param int $level
+ *   Used internally to determine the current level of the menu.
+ */
+function _bootstrap_book_fix_theme_hooks($bid, array &$element, $level = 0) {
+  $hook = $level === 0 ? $bid : 'sub_menu__' . $bid;
+  $element['#theme_wrappers'] = array('menu_tree__book_toc__' . $hook);
+  foreach (element_children($element) as $child) {
+    $element[$child]['#theme'] = 'menu_link__book_toc__' . $hook;
+    // Iterate through all child menu items as well.
+    if (!empty($element[$child]['#below'])) {
+      _bootstrap_book_fix_theme_hooks($bid, $element[$child]['#below'], ($level + 1));
+    }
+  }
+}

+ 45 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-carousel.tpl.php

@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display a Bootstrap carousel component.
+ *
+ * @todo Fill out list of available variables.
+ *
+ * @ingroup templates
+ */
+?>
+<div<?php print $attributes; ?>>
+  <?php if($indicators && ($item_length = count($items))): ?>
+    <ol class="carousel-indicators">
+      <?php for ($i = 0; $i < $item_length; $i++): ?>
+        <li data-target="<?php print $target; ?>" data-slide-to="<?php print $i; ?>"<?php print ($start_index === $i ? ' class="active"' : ''); ?>></li>
+      <?php endfor; ?>
+    </ol>
+  <?php endif; ?>
+  <div class="carousel-inner">
+    <?php foreach ($items as $i => $item): ?>
+      <div class="item<?php print ($start_index === $i ? ' active' : ''); ?>">
+        <?php print render($item['image']); ?>
+        <?php if ($item['title'] || $item['description']): ?>
+          <div class="carousel-caption">
+            <?php if ($item['title']): ?>
+              <h3><?php print $item['title']; ?></h3>
+            <?php endif; ?>
+            <?php if ($item['description']): ?>
+              <p><?php print $item['description']; ?></p>
+            <?php endif; ?>
+          </div>
+        <?php endif; ?>
+      </div>
+    <?php endforeach; ?>
+  </div>
+  <?php if($controls): ?>
+    <a class="left carousel-control" href="<?php print $target; ?>" role="button" data-slide="prev">
+      <span class="glyphicon glyphicon-chevron-left"></span>
+    </a>
+    <a class="right carousel-control" href="<?php print $target; ?>" role="button" data-slide="next">
+      <span class="glyphicon glyphicon-chevron-right"></span>
+    </a>
+  <?php endif; ?>
+</div>

+ 84 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-carousel.vars.php

@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "bootstrap_carousel" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "bootstrap_carousel" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap-carousel.tpl.php
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_bootstrap_carousel(array &$variables) {
+  $variables['attributes']['class'][] = 'carousel';
+  $variables['attributes']['class'][] = 'slide';
+  $variables['attributes']['data-ride'] = 'carousel';
+  if (empty($variables['attributes']['id'])) {
+    $variables['attributes']['id'] = drupal_html_id('carousel');
+  }
+  $default_data_attributes = array(
+    'interval' => 5000,
+    'pause' => TRUE,
+    'wrap' => TRUE,
+  );
+  foreach ($default_data_attributes as $name => $value) {
+    if ($variables[$name] !== $value) {
+      // Convert PHP booleans to the JSON equivalent, otherwise they'll be
+      // interpreted as integers when they're parsed.
+      if (is_bool($variables[$name])) {
+        $variables[$name] = $variables[$name] ? 'true' : 'false';
+      }
+      $variables['attributes']['data-' . $name] = $variables[$name];
+    }
+  }
+}
+
+/**
+ * Processes variables for the "bootstrap_carousel" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap-carousel.tpl.php
+ *
+ * @ingroup theme_process
+ */
+function bootstrap_process_bootstrap_carousel(array &$variables) {
+  $variables['target'] = '#' . $variables['attributes']['id'];
+  $variables['attributes'] = drupal_attributes($variables['attributes']);
+
+  // Ensure the item arrays are constructed properly for the template.
+  foreach ($variables['items'] as $delta => $item) {
+    // Convert items that are string into the appropriate array structure.
+    if (is_string($item)) {
+      $variables['items'][$delta] = array(
+        'image' => $item,
+      );
+    }
+    // Populate defaults.
+    $variables['items'][$delta] += array(
+      'title' => NULL,
+      'description' => NULL,
+      'url' => NULL,
+    );
+
+    if (!empty($variables['items'][$delta]['title'])) {
+      $variables['items'][$delta]['title'] = is_scalar($item['title']) ? filter_xss_admin($item['title']) : render($item['title']);
+    }
+
+    if (!empty($variables['items'][$delta]['description'])) {
+      $variables['items'][$delta]['description'] = is_scalar($item['description']) ? filter_xss_admin($item['description']) : render($item['description']);
+    }
+
+  }
+}

+ 21 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-dropdown.func.php

@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_bootstrap_dropdown().
+ */
+
+/**
+ * Returns HTML for a Bootstrap dropdown component.
+ *
+ * @param array $variables
+ *   An associative array of variables.
+ *
+ * @return string
+ *   The constructed HTML markup.
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_bootstrap_dropdown(array $variables) {
+  return drupal_render($variables['dropdown']);
+}

+ 128 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-dropdown.vars.php

@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "bootstrap_dropdown" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "bootstrap_dropdown" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap_bootstrap_dropdown()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_bootstrap_dropdown(array &$variables) {
+  $element = &$variables['element'];
+
+  // Provide defaults.
+  $element += array(
+    '#wrapper_attributes' => NULL,
+    '#attributes' => NULL,
+    '#alignment' => NULL,
+    '#toggle' => NULL,
+    '#items' => NULL,
+  );
+
+  // Dropdown vertical alignment.
+  $element['#wrapper_attributes']['class'][] = 'dropdown';
+  if ($element['#alignment'] === 'up' || (is_array($element['#alignment']) && in_array('up', $element['#alignment']))) {
+    $element['#wrapper_attributes']['class'][] = 'dropup';
+  }
+
+  if (isset($element['#toggle'])) {
+    if (is_string($element['#toggle'])) {
+      $element['#toggle'] = array(
+        '#theme' => 'link__bootstrap_dropdown__toggle',
+        '#text' => filter_xss_admin($element['#toggle']),
+        '#path' => '#',
+        '#options' => array(
+          'attributes' => array(),
+          'html' => TRUE,
+          'external' => TRUE,
+        ),
+      );
+    }
+    if (isset($element['#toggle']['#options']['attributes'])) {
+      $element['#toggle']['#options']['attributes']['class'][] = 'dropdown-toggle';
+      $element['#toggle']['#options']['attributes']['data-toggle'] = 'dropdown';
+    }
+    else {
+      $element['#toggle']['#attributes']['class'][] = 'dropdown-toggle';
+      $element['#toggle']['#attributes']['data-toggle'] = 'dropdown';
+    }
+  }
+
+  // Menu items.
+  $element['#attributes']['role'] = 'menu';
+  $element['#attributes']['class'][] = 'dropdown-menu';
+  if ($element['#alignment'] === 'right' || (is_array($element['#alignment']) && in_array('right', $element['#alignment']))) {
+    $element['#attributes']['class'][] = 'dropdown-menu-right';
+  }
+}
+
+/**
+ * Processes variables for the "bootstrap_dropdown" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap_bootstrap_dropdown()
+ *
+ * @ingroup theme_process
+ */
+function bootstrap_process_bootstrap_dropdown(array &$variables) {
+  $element = &$variables['element'];
+
+  $items = array();
+  foreach ($element['#items'] as $data) {
+    $item_classes = array();
+
+    // Dividers.
+    if (empty($data)) {
+      $data = '';
+      $item_classes[] = 'divider';
+    }
+    // Headers (must be a string).
+    elseif (is_array($data) && (!empty($data['header']) || !empty($data['#header']))) {
+      $item_classes[] = 'dropdown-header';
+    }
+    // Disabled.
+    elseif (is_array($data) && (!empty($data['disabled']) || !empty($data['#disabled']))) {
+      $item_classes[] = 'disabled';
+    }
+    // Active.
+    elseif (is_array($data) && (!empty($data['active']) || !empty($data['#active']))) {
+      $item_classes[] = 'active';
+    }
+
+    // Construct item_list item.
+    $item = array(
+      'data' => render($data),
+      'role' => 'presentation',
+    );
+    if (!empty($item_classes)) {
+      $item['class'] = $item_classes;
+    }
+    $items[] = $item;
+  }
+
+  // Create the dropdown.
+  $variables['dropdown'] = array(
+    '#theme_wrappers' => array('container'),
+    '#attributes' => $element['#wrapper_attributes'],
+    'toggle' => $element['#toggle'],
+    'items' => array(
+      '#theme' => 'item_list__bootstrap_dropdown',
+      '#items' => $items,
+      '#attributes' => $element['#attributes'],
+    ),
+  );
+}

+ 33 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-modal.tpl.php

@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display a Bootstrap modal component.
+ *
+ * Markup for Bootstrap modals.
+ *
+ * Variables:
+ * - $attributes: Attributes for the outer modal div.
+ * - $dialog_attributes: Attributes for the inner modal div.
+ * - $heading: Modal title.
+ * - $body: The rendered body of the modal.
+ * - $footer: The rendered footer of the modal.
+ * - $size: The size of the modal. Can be empty, "sm" or "lg". This is
+ *   automatically added in the $dialog_attributes. See
+ *   bootstrap_preprocess_bootstrap_modal().
+ *
+ * @ingroup templates
+ */
+?>
+<div<?php print $attributes; ?>>
+  <div<?php print $dialog_attributes; ?>>
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+        <h4 class="modal-title"><?php print $heading; ?></h4>
+      </div>
+      <div class="modal-body"><?php print $body; ?></div>
+      <div class="modal-footer"><?php print $footer; ?></div>
+    </div>
+  </div>
+</div>

+ 60 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-modal.vars.php

@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "bootstrap_modal" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "bootstrap_modal" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap-modal.tpl.php
+ *
+ * @ingroup theme_preprocess
+ *
+ * @todo: Replace with "bootstrap_effect_fade" theme setting.
+ */
+function bootstrap_preprocess_bootstrap_modal(array &$variables) {
+  if (empty($variables['attributes']['id'])) {
+    $variables['attributes']['id'] = drupal_html_id(strip_tags($variables['heading']));
+  }
+  $variables['attributes']['class'][] = 'modal';
+  $variables['attributes']['class'][] = 'fade';
+  $variables['attributes']['tabindex'] = -1;
+  $variables['attributes']['role'] = 'dialog';
+  $variables['attributes']['aria-hidden'] = 'true';
+  $variables['dialog_attributes']['class'][] = 'modal-dialog';
+
+  if (!empty($variables['size'])) {
+    $variables['dialog_attributes']['class'][] = drupal_html_class('modal-' . $variables['size']);
+  }
+}
+
+/**
+ * Processes variables for the "bootstrap_modal" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap-modal.tpl.php
+ *
+ * @ingroup theme_process
+ */
+function bootstrap_process_bootstrap_modal(array &$variables) {
+  $variables['attributes'] = drupal_attributes($variables['attributes']);
+  $variables['dialog_attributes'] = drupal_attributes($variables['dialog_attributes']);
+
+  $html = !empty($variables['html_heading']);
+  $heading = $html && is_scalar($variables['heading']) ? filter_xss_admin($variables['heading']) : render($variables['heading']);
+  $variables['heading'] = $html ? $heading : check_plain($heading);
+
+  $variables['body'] = render($variables['body']);
+  $variables['footer'] = render($variables['footer']);
+}

+ 29 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-panel.tpl.php

@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display a Bootstrap panel component.
+ *
+ * @todo Fill out list of available variables.
+ *
+ * @ingroup templates
+ */
+?>
+<fieldset <?php print $attributes; ?>>
+  <?php if ($title): ?>
+    <?php if ($collapsible): ?>
+    <legend class="panel-heading">
+      <a href="<?php print $target; ?>" class="panel-title fieldset-legend<?php print ($collapsed ? ' collapsed' : ''); ?>" data-toggle="collapse"><?php print $title; ?></a>
+    </legend>
+    <?php else: ?>
+    <legend class="panel-heading">
+      <span class="panel-title fieldset-legend"><?php print $title; ?></span>
+    </legend>
+    <?php endif; ?>
+  <?php endif; ?>
+  <div<?php print $body_attributes; ?>>
+    <?php if ($description): ?><div class="help-block"><?php print $description; ?></div><?php
+    endif; ?>
+    <?php print $content; ?>
+  </div>
+</fieldset>

+ 127 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-panel.vars.php

@@ -0,0 +1,127 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "bootstrap_panel" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "bootstrap_panel" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap-panel.tpl.php
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_bootstrap_panel(array &$variables) {
+  // Temporarily provide field_group "support" until properly "fixed" upstream.
+  // @see https://www.drupal.org/project/bootstrap/issues/2910624
+  if (!empty($variables['element']['#group']->format_type) && $variables['element']['#group']->format_type == 'htab') {
+    $variables['element']['#collapsed'] = FALSE;
+  }
+
+  $element = &$variables['element'];
+
+  // Set the element's attributes.
+  element_set_attributes($element, array('id'));
+
+  // Retrieve the attributes for the element.
+  $attributes = &_bootstrap_get_attributes($element);
+
+  // Add panel and panel-default classes.
+  $attributes['class'][] = 'panel';
+  $attributes['class'][] = 'panel-default';
+
+  // states.js requires form-wrapper on fieldset to work properly.
+  $attributes['class'][] = 'form-wrapper';
+
+  // Handle collapsible panels.
+  $variables['collapsible'] = FALSE;
+  if (isset($element['#collapsible'])) {
+    $variables['collapsible'] = $element['#collapsible'];
+  }
+  $variables['collapsed'] = FALSE;
+  if (isset($element['#collapsed'])) {
+    $variables['collapsed'] = $element['#collapsed'];
+    // Remove collapsed class as it should only be applied to the body.
+    _bootstrap_remove_class('collapsed', $element);
+  }
+
+  // Generate a unique identifier for the fieldset wrapper.
+  if (!isset($attributes['id'])) {
+    $attributes['id'] = drupal_html_id('bootstrap-panel');
+  }
+
+  // Get body attributes.
+  $body_attributes = &_bootstrap_get_attributes($element, 'body_attributes');
+
+  _bootstrap_add_class('panel-body', $element, 'body_attributes');
+
+  // Add default .panel-body class.
+  $body_classes = array('panel-body');
+
+  // Add more classes to the body if collapsible.
+  if ($variables['collapsible']) {
+    $body_classes[] = 'panel-collapse';
+    $body_classes[] = 'collapse';
+    $body_classes[] = 'fade';
+    $body_classes[] = $variables['collapsed'] ? 'collapsed' : 'in';
+  }
+  _bootstrap_add_class($body_classes, $element, 'body_attributes');
+
+  // Generate a unique identifier for the body.
+  if (!isset($body_attributes['id'])) {
+    $body_attributes['id'] = drupal_html_id($attributes['id'] . '--body');
+  }
+
+  // Set the target to the body element.
+  $variables['target'] = '#' . $body_attributes['id'];
+
+  // Build the panel content.
+  $variables['content'] = $element['#children'];
+  if (isset($element['#value'])) {
+    $variables['content'] .= $element['#value'];
+  }
+
+  // Iterate over optional variables.
+  $keys = array(
+    'description',
+    'prefix',
+    'suffix',
+    'title',
+  );
+  foreach ($keys as $key) {
+    $variables[$key] = !empty($element["#$key"]) ? $element["#$key"] : FALSE;
+  }
+
+  // Add the attributes.
+  $variables['attributes'] = $attributes;
+  $variables['body_attributes'] = $body_attributes;
+}
+
+/**
+ * Processes variables for the "bootstrap_panel" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap-panel.tpl.php
+ *
+ * @ingroup theme_process
+ */
+function bootstrap_process_bootstrap_panel(array &$variables) {
+  $variables['attributes'] = drupal_attributes($variables['attributes']);
+  $variables['body_attributes'] = drupal_attributes($variables['body_attributes']);
+  if (!empty($variables['title'])) {
+    $variables['title'] = filter_xss_admin(render($variables['title']));
+  }
+  if (!empty($variables['description'])) {
+    $variables['description'] = filter_xss_admin(render($variables['description']));
+  }
+}

+ 27 - 0
mydata/themes/bootstrap/templates/bootstrap/bootstrap-search-form-wrapper.func.php

@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_bootstrap_search_form_wrapper().
+ */
+
+/**
+ * Returns HTML for the Bootstrap search form wrapper.
+ *
+ * @param array $variables
+ *   An associative array of variables.
+ *
+ * @return string
+ *   The constructed HTML markup.
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_bootstrap_search_form_wrapper(array $variables) {
+  $output = '<div class="input-group">';
+  $output .= $variables['element']['#children'];
+  $output .= '<span class="input-group-btn">';
+  $output .= '<button type="submit" class="btn btn-primary">' . _bootstrap_icon('search', t('Search')) . '</button>';
+  $output .= '</span>';
+  $output .= '</div>';
+  return $output;
+}

+ 36 - 0
mydata/themes/bootstrap/templates/date/date-views-pager.tpl.php

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Displays the date views pager.
+ *
+ * Available variables:
+ * - $attributes: A string of attributes to apply to the pager wrapper element.
+ * - $items: A render array of pagination items.
+ * - $mini: Flag indicating whether simple pager items should be shown.
+ * - $nav_title: The formatted title for this view. In the case of block views,
+ *   it will be a link to the full view, otherwise it will be the formatted name
+ *   of the year, month, day, or week. See theme_date_nav_title() for more
+ *   details.
+ * - $prev_options: An list of link options that is passed to the link theme
+ *   hook.
+ * - $prev_url: URL for the previous calendar page.
+ * - $next_options: An list of link options that is passed to the link theme
+ *   hook.
+ * - $next_url: URL for the next calendar page.
+ * - $plugin: The pager plugin object. This contains the view.
+ *
+ * @see bootstrap_process_date_views_pager()
+ * @see bootstrap_preprocess_date_views_pager()
+ * @see template_preprocess_date_views_pager()
+ *
+ * @ingroup templates
+ */
+?>
+<?php if (!empty($pager_prefix)): ?>
+<?php print $pager_prefix; ?>
+<?php endif; ?>
+<nav<?php print $attributes;?>>
+  <?php print render($items); ?>
+  <h3><?php print $nav_title ?></h3>
+</nav>

+ 108 - 0
mydata/themes/bootstrap/templates/date/date-views-pager.vars.php

@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "date_views_pager" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "date_views_pager" theme hook.
+ *
+ * See template for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see date-views-pager.tpl.php
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_date_views_pager(array &$variables) {
+  $mini = !empty($variables['mini']);
+
+  // Link types.
+  $types = array(
+    // Because this is using the "date_nav" context, this must use "Prev"
+    // instead of the full English word "Previous".
+    // @todo Should this be fixed upstream in the date/date_views module?
+    'prev' => t('Prev', array(), array('context' => 'date_nav')),
+    'next' => t('Next', array(), array('context' => 'date_nav')),
+  );
+
+  // Icon map.
+  $icons = array(
+    'prev' => array(
+      'name' => 'menu-left',
+      'default' => '&laquo;&nbsp;',
+      'position' => 'before',
+    ),
+    'next' => array(
+      'name' => 'menu-right',
+      'default' => '&nbsp;&raquo;',
+      'position' => 'after',
+    ),
+  );
+
+  // Create necessary links.
+  $items = array();
+  foreach ($types as $type => $text) {
+    $item_classes = array($type);
+
+    $options = isset($variables[$type . '_options']) ? $variables[$type . '_options'] : array();
+    $options += array('attributes' => array());
+
+    $url = $variables[$type . '_url'];
+    // Make the item disabled if there is no URL.
+    if (!$url) {
+      $url = '#';
+      $item_classes[] = 'disabled';
+      $options['absolute'] = TRUE;
+      $options['external'] = TRUE;
+    }
+    // Convert titles into tooltips, if enabled.
+    elseif (!empty($options['attributes']['title']) && bootstrap_setting('tooltip_enabled')) {
+      $options['attributes']['data-toggle'] = 'tooltip';
+      $options['attributes']['data-placement'] = 'bottom';
+    }
+
+    // Create a link.
+    $link = array(
+      '#theme' => 'link__date_views__pager__' . $type,
+      '#text' => $text,
+      '#path' => $url,
+      '#options' => $options,
+    );
+
+    // Add relevant icon.
+    if (isset($icons[$type])) {
+      $icon = $icons[$type];
+      $link['#icon'] = _bootstrap_icon($icon['name'], $icon['default']);
+      $link['#icon_position'] = $mini ? 'icon_only' : $icon['position'];
+    }
+
+    $items[$type] = array(
+      'class' => $item_classes,
+      'data' => $link,
+    );
+  }
+
+  // Add items render array.
+  $variables['items'] = array(
+    '#theme' => 'item_list__date_views__pager',
+    '#attributes' => array('class' => array('pagination', 'pull-right')),
+    '#items' => $items,
+  );
+
+  // Add default classes for the <nav> wrapper.
+  $variables['attributes_array']['class'][] = 'clearfix';
+  $variables['attributes_array']['class'][] = 'date-nav-wrapper';
+
+  // This is not mentioned anywhere other than in the original module's
+  // template file. However, to keep BC, these need to be merged just in case.
+  if (!empty($variables['extra_classes'])) {
+    if (is_string($variables['extra_classes'])) {
+      $variables['extra_classes'] = explode(' ', $variables['extra_classes']);
+    }
+    $variables['attributes_array']['class'] = array_merge(isset($variables['attributes']['class']) ? $variables['attributes']['class'] : array(), $variables['extra_classes']);
+  }
+}

+ 69 - 0
mydata/themes/bootstrap/templates/file/file-managed-file.func.php

@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_file_managed_file().
+ */
+
+/**
+ * Returns HTML for a managed file element.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: A render element representing the file.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_file_managed_file()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_file_managed_file(array $variables) {
+  $output = '';
+  $element = $variables['element'];
+
+  $attributes = array();
+
+  // For Webform use, do not add the id to the wrapper.
+  if (isset($element['#id']) && empty($element['#webform_component'])) {
+    $attributes['id'] = $element['#id'];
+  }
+
+  if (!empty($element['#attributes']['class'])) {
+    $attributes['class'] = (array) $element['#attributes']['class'];
+  }
+  $attributes['class'][] = 'form-managed-file';
+  $attributes['class'][] = 'input-group';
+
+  $element['upload_button']['#attributes']['class'][] = 'btn-primary';
+  $element['upload_button']['#prefix'] = '<span class="input-group-btn">';
+  $element['upload_button']['#suffix'] = '</span>';
+  $element['remove_button']['#prefix'] = '<span class="input-group-btn">';
+  $element['remove_button']['#suffix'] = '</span>';
+  $element['remove_button']['#attributes']['class'][] = 'btn-danger';
+
+  if (!empty($element['filename'])) {
+    $element['filename']['#prefix'] = '<div class="form-control">';
+    $element['filename']['#suffix'] = '</div>';
+  }
+
+  // This wrapper is required to apply JS behaviors and CSS styling.
+  $output .= '<div' . drupal_attributes($attributes) . '>';
+
+  // Immediately render hidden elements before the rest of the output.
+  // The uploadprogress extension requires that the hidden identifier input
+  // element appears before the file input element. They must also be siblings
+  // inside the same parent element.
+  // @see https://www.drupal.org/node/2155419
+  foreach (element_children($element) as $child) {
+    if (isset($element[$child]['#type']) && $element[$child]['#type'] === 'hidden') {
+      $output .= drupal_render($element[$child]);
+    }
+  }
+
+  // Render the rest of the element.
+  $output .= drupal_render_children($element);
+  $output .= '</div>';
+  return $output;
+}

+ 96 - 0
mydata/themes/bootstrap/templates/file/file-upload-help.func.php

@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_file_upload_help().
+ */
+
+/**
+ * Returns HTML for help text based on file upload validators.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - description: The normal description for this field, specified by the
+ *     user.
+ *   - upload_validators: An array of upload validators as used in
+ *     $element['#upload_validators'].
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_file_upload_help()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_file_upload_help(array $variables) {
+  // If popover's are disabled, just theme this normally.
+  if (!bootstrap_setting('popover_enabled')) {
+    return theme_file_upload_help($variables);
+  }
+
+  $build = array();
+  if (!empty($variables['description'])) {
+    $build['description'] = array(
+      '#markup' => $variables['description'] . '<br>',
+    );
+  }
+
+  $descriptions = array();
+  $upload_validators = $variables['upload_validators'];
+  if (isset($upload_validators['file_validate_size'])) {
+    $descriptions[] = t('Files must be less than !size.', array('!size' => '<strong>' . format_size($upload_validators['file_validate_size'][0]) . '</strong>'));
+  }
+  if (isset($upload_validators['file_validate_extensions'])) {
+    $descriptions[] = t('Allowed file types: !extensions.', array('!extensions' => '<strong>' . check_plain($upload_validators['file_validate_extensions'][0]) . '</strong>'));
+  }
+  if (isset($upload_validators['file_validate_image_resolution'])) {
+    $max = $upload_validators['file_validate_image_resolution'][0];
+    $min = $upload_validators['file_validate_image_resolution'][1];
+    if ($min && $max && $min == $max) {
+      $descriptions[] = t('Images must be exactly !size pixels.', array('!size' => '<strong>' . $max . '</strong>'));
+    }
+    elseif ($min && $max) {
+      $descriptions[] = t('Images must be between !min and !max pixels.', array('!min' => '<strong>' . $min . '</strong>', '!max' => '<strong>' . $max . '</strong>'));
+    }
+    elseif ($min) {
+      $descriptions[] = t('Images must be larger than !min pixels.', array('!min' => '<strong>' . $min . '</strong>'));
+    }
+    elseif ($max) {
+      $descriptions[] = t('Images must be smaller than !max pixels.', array('!max' => '<strong>' . $max . '</strong>'));
+    }
+  }
+
+  if ($descriptions) {
+    $id = drupal_html_id('upload-instructions');
+    $build['instructions'] = array(
+      '#theme' => 'link__file_upload_requirements',
+      // @todo remove space between icon/text and fix via styling.
+      '#text' => _bootstrap_icon('question-sign') . ' ' . t('More information'),
+      '#path' => '#',
+      '#options' => array(
+        'attributes' => array(
+          'data-toggle' => 'popover',
+          'data-target' => "#$id",
+          'data-html' => TRUE,
+          'data-placement' => 'bottom',
+          'data-title' => t('File requirements'),
+        ),
+        'html' => TRUE,
+        'external' => TRUE,
+      ),
+    );
+    $build['requirements'] = array(
+      '#theme_wrappers' => array('container__file_upload_requirements'),
+      '#attributes' => array(
+        'id' => $id,
+        'class' => array('element-invisible', 'help-block'),
+      ),
+    );
+    $build['requirements']['validators'] = array(
+      '#theme' => 'item_list__file_upload_requirements',
+      '#items' => $descriptions,
+    );
+  }
+
+  return drupal_render($build);
+}

+ 135 - 0
mydata/themes/bootstrap/templates/file/file-widget-multiple.func.php

@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_file_widget_multiple().
+ */
+
+/**
+ * Returns HTML for a group of file upload widgets.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: A render element representing the widgets.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_file_widget_multiple()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_file_widget_multiple(array $variables) {
+  $element = $variables['element'];
+
+  // Special ID and classes for draggable tables.
+  $weight_class = $element['#id'] . '-weight';
+  $table_id = $element['#id'] . '-table';
+
+  // Build up a table of applicable fields.
+  $headers = array();
+  $headers[] = t('File information');
+  if ($element['#display_field']) {
+    $headers[] = array(
+      'data' => t('Display'),
+      'class' => array('checkbox'),
+    );
+  }
+  $headers[] = t('Weight');
+  $headers[] = t('Operations');
+
+  // Get our list of widgets in order (needed when the form comes back after
+  // preview or failed validation).
+  $widgets = array();
+  foreach (element_children($element) as $key) {
+    $widgets[] = &$element[$key];
+  }
+  usort($widgets, '_field_sort_items_value_helper');
+
+  $rows = array();
+  foreach ($widgets as $key => &$widget) {
+    // Save the uploading row for last.
+    if (!isset($widget['#file']) || $widget['#file'] === FALSE) {
+      $widget['#title'] = $element['#file_upload_title'];
+      $widget['#description'] = $element['#file_upload_description'];
+      continue;
+    }
+
+    // Delay rendering of the buttons, so that they can be rendered later in the
+    // "operations" column.
+    $operations_elements = array();
+    foreach (element_children($widget) as $sub_key) {
+      if (isset($widget[$sub_key]['#type']) && $widget[$sub_key]['#type'] == 'submit') {
+        hide($widget[$sub_key]);
+        $operations_elements[] = &$widget[$sub_key];
+      }
+    }
+
+    // Delay rendering of the "Display" option and the weight selector, so that
+    // each can be rendered later in its own column.
+    if ($element['#display_field']) {
+      hide($widget['display']);
+    }
+    hide($widget['_weight']);
+
+    // Render everything else together in a column, without the normal wrappers.
+    $widget['#theme_wrappers'] = array();
+    $information = drupal_render($widget);
+
+    // Render the previously hidden elements, using render() instead of
+    // drupal_render(), to undo the earlier hide().
+    $operations = '';
+    foreach ($operations_elements as $operation_element) {
+      $operation_element['#attributes']['class'][] = 'btn-xs';
+      switch ($operation_element['#value']) {
+        case t('Remove'):
+          $operation_element['#icon'] = _bootstrap_icon('remove');
+          break;
+      }
+      $operations .= render($operation_element);
+    }
+    $display = '';
+    if ($element['#display_field']) {
+      unset($widget['display']['#title']);
+      $display = array(
+        'data' => render($widget['display']),
+        'class' => array('checkbox'),
+      );
+    }
+    $widget['_weight']['#attributes']['class'] = array($weight_class);
+    $weight = render($widget['_weight']);
+
+    // Arrange the row with all of the rendered columns.
+    $row = array();
+    $row[] = $information;
+    if ($element['#display_field']) {
+      $row[] = $display;
+    }
+    $row[] = $weight;
+    $row[] = $operations;
+    $rows[] = array(
+      'data' => $row,
+      'class' => isset($widget['#attributes']['class']) ? array_merge($widget['#attributes']['class'], array('draggable')) : array('draggable'),
+    );
+  }
+
+  drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class);
+
+  $output = '';
+  if (!empty($rows)) {
+    $table = array(
+      '#theme' => 'table',
+      '#header' => $headers,
+      '#rows' => $rows,
+      '#attributes' => array(
+        'id' => $table_id,
+        'class' => array(
+          'managed-files',
+        ),
+      ),
+    );
+    $output = drupal_render($table);
+  }
+  $output .= drupal_render_children($element);
+  return $output;
+}

+ 54 - 0
mydata/themes/bootstrap/templates/file/file-widget.func.php

@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_file_widget().
+ */
+
+/**
+ * Returns HTML for an individual file upload widget.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: A render element representing the widget.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_file_widget()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_file_widget(array $variables) {
+  $output = '';
+  $element = $variables['element'];
+  $element['upload_button']['#attributes']['class'][] = 'btn-primary';
+  $element['upload_button']['#prefix'] = '<span class="input-group-btn">';
+  $element['upload_button']['#suffix'] = '</span>';
+
+  // The "form-managed-file" class is required for proper Ajax functionality.
+  if (!empty($element['filename'])) {
+    $output .= '<div class="file-widget form-managed-file clearfix">';
+    // Add the file size after the file name.
+    $element['filename']['#markup'] .= ' <span class="file-size badge">' . format_size($element['#file']->filesize) . '</span>';
+  }
+  else {
+    $output .= '<div class="file-widget form-managed-file clearfix input-group">';
+  }
+
+  // Immediately render hidden elements before the rest of the output.
+  // The uploadprogress extension requires that the hidden identifier input
+  // element appears before the file input element. They must also be siblings
+  // inside the same parent element.
+  // @see https://www.drupal.org/node/2155419
+  foreach (element_children($element) as $child) {
+    if (isset($element[$child]['#type']) && $element[$child]['#type'] === 'hidden') {
+      $output .= drupal_render($element[$child]);
+    }
+  }
+
+  // Render the rest of the element.
+  $output .= drupal_render_children($element);
+  $output .= '</div>';
+  return $output;
+}

+ 30 - 0
mydata/themes/bootstrap/templates/filter/filter-tips-more-info.func.php

@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_filter_tips_more_info().
+ */
+
+/**
+ * Returns HTML for a link to the more extensive filter tips.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_filter_tips_more_info()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_filter_tips_more_info() {
+  $attributes = array(
+    'target' => '_blank',
+    'title' => t('Opens in new window'),
+  );
+  if (bootstrap_setting('tooltip_enabled')) {
+    $attributes['data-toggle'] = 'tooltip';
+  }
+  return l(_bootstrap_icon('question-sign') . t('More information about text formats'), 'filter/tips', array(
+    'html' => TRUE,
+    'attributes' => $attributes,
+  ));
+}

+ 120 - 0
mydata/themes/bootstrap/templates/filter/filter-tips.func.php

@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_filter_tips().
+ */
+
+/**
+ * Returns HTML for a set of filter tips.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tips: An array containing descriptions and a CSS ID in the form of
+ *     'module-name/filter-id' (only used when $long is TRUE) for each
+ *     filter in one or more text formats. Example:.
+ *
+ * @code
+ *       array(
+ *         'Full HTML' => array(
+ *           0 => array(
+ *             'tip' => 'Web page addresses and e-mail addresses turn into links automatically.',
+ *             'id' => 'filter/2',
+ *           ),
+ *         ),
+ *       );
+ * @endcode
+ *   - long: (optional) Whether the passed-in filter tips contain extended
+ *     explanations, i.e. intended to be output on the path 'filter/tips'
+ *     (TRUE), or are in a short format, i.e. suitable to be displayed below a
+ *     form element. Defaults to FALSE.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_filter_tips()
+ * @see _filter_tips()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_filter_tips(array $variables) {
+  $format_id = arg(2);
+  $current_path = current_path();
+  $tips = _filter_tips(-1, TRUE);
+
+  // Create a place holder for the tabs.
+  $build['tabs'] = array(
+    '#theme' => 'item_list',
+    '#items' => array(),
+    '#attributes' => array(
+      'class' => array(
+        'nav',
+        'nav-tabs',
+      ),
+      'role' => 'tablist',
+    ),
+  );
+
+  // Create a placeholder for the panes.
+  $build['panes'] = array(
+    '#theme_wrappers' => array('container'),
+    '#attributes' => array(
+      'class' => array(
+        'tab-content',
+      ),
+    ),
+  );
+
+  foreach ($tips as $name => $list) {
+    $machine_name = str_replace('-', '_', drupal_html_class($name));
+    $tab = array(
+      'data' => array(
+        '#type' => 'link',
+        '#title' => check_plain($name),
+        '#href' => $current_path,
+        '#attributes' => array(
+          'role' => 'tab',
+          'data-toggle' => 'tab',
+        ),
+        '#options' => array(
+          'fragment' => $machine_name,
+        ),
+      ),
+    );
+    if (!$format_id || $format_id === $machine_name) {
+      $tab['class'][] = 'active';
+      $format_id = $machine_name;
+    }
+    $build['tabs']['#items'][] = $tab;
+
+    // Extract the actual tip.
+    $tiplist = array();
+    foreach ($list as $tip) {
+      $tiplist[] = $tip['tip'];
+    }
+
+    // Construct the pane.
+    $pane = array(
+      '#theme_wrappers' => array('container'),
+      '#attributes' => array(
+        'class' => array(
+          'tab-pane',
+          'fade',
+        ),
+        'id' => $machine_name,
+      ),
+      'list' => array(
+        '#theme' => 'item_list',
+        '#items' => $tiplist,
+      ),
+    );
+    if ($format_id === $machine_name) {
+      $pane['#attributes']['class'][] = 'active';
+      $pane['#attributes']['class'][] = 'in';
+      $format_id = $machine_name;
+    }
+    $build['panes'][] = $pane;
+  }
+
+  return drupal_render($build);
+}

+ 31 - 0
mydata/themes/bootstrap/templates/filter/text-format-wrapper.func.php

@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_text_format_wrapper().
+ */
+
+/**
+ * Returns HTML for a text format-enabled form element.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: A render element containing #children and #description.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_text_format_wrapper()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_text_format_wrapper(array $variables) {
+  $element = $variables['element'];
+  $output = '<div class="text-format-wrapper">';
+  $output .= $element['#children'];
+  if (!empty($element['#description'])) {
+    $output .= '<p class="help-block">' . $element['#description'] . '</p>';
+  }
+  $output .= "</div>\n";
+  return $output;
+}

+ 29 - 0
mydata/themes/bootstrap/templates/icon/icon.vars.php

@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "icon" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "icon" theme hook.
+ *
+ * Bootstrap requires an additional "glyphicon" class for all icons.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see icon_preprocess_icon_image()
+ * @see template_preprocess_icon()
+ * @see theme_icon()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_icon(array &$variables) {
+  $bundle = &$variables['bundle'];
+  if ($bundle['provider'] === 'bootstrap') {
+    $variables['attributes']['class'][] = 'glyphicon';
+  }
+}

+ 43 - 0
mydata/themes/bootstrap/templates/image/image-widget.func.php

@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_image_widget().
+ */
+
+/**
+ * Returns HTML for an image field widget.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: A render element representing the image field widget.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_image_widget()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_image_widget(array $variables) {
+  $element = $variables['element'];
+  $output = '';
+  $output .= '<div class="image-widget form-managed-file clearfix">';
+
+  if (isset($element['preview'])) {
+    $output .= '<div class="image-preview">';
+    $output .= drupal_render($element['preview']);
+    $output .= '</div>';
+  }
+
+  $output .= '<div class="image-widget-data">';
+  if (!empty($element['fid']['#value'])) {
+    $element['filename']['#markup'] = '<div class="form-group">' . $element['filename']['#markup'] . ' <span class="file-size badge">' . format_size($element['#file']->filesize) . '</span></div>';
+  }
+
+  $output .= drupal_render_children($element);
+  $output .= '</div>';
+  $output .= '</div>';
+
+  return $output;
+}

+ 101 - 0
mydata/themes/bootstrap/templates/menu/menu-link.func.php

@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_menu_link() and suggestion(s).
+ */
+
+/**
+ * Returns HTML for a menu link and submenu.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: Structured array data for a menu link.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_menu_link()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_menu_link(array $variables) {
+  $element = $variables['element'];
+  $sub_menu = '';
+
+  $options = !empty($element['#localized_options']) ? $element['#localized_options'] : array();
+
+  // Check plain title if "html" is not set, otherwise, filter for XSS attacks.
+  $title = empty($options['html']) ? check_plain($element['#title']) : filter_xss_admin($element['#title']);
+
+  // Ensure "html" is now enabled so l() doesn't double encode. This is now
+  // safe to do since both check_plain() and filter_xss_admin() encode HTML
+  // entities. See: https://www.drupal.org/node/2854978
+  $options['html'] = TRUE;
+
+  $href = $element['#href'];
+  $attributes = !empty($element['#attributes']) ? $element['#attributes'] : array();
+
+  if ($element['#below']) {
+    // Prevent dropdown functions from being added to management menu so it
+    // does not affect the navbar module.
+    if (($element['#original_link']['menu_name'] == 'management') && (module_exists('navbar'))) {
+      $sub_menu = drupal_render($element['#below']);
+    }
+    elseif ((!empty($element['#original_link']['depth'])) && ($element['#original_link']['depth'] == 1)) {
+      // Add our own wrapper.
+      unset($element['#below']['#theme_wrappers']);
+      $sub_menu = '<ul class="dropdown-menu">' . drupal_render($element['#below']) . '</ul>';
+
+      // Generate as standard dropdown.
+      $title .= ' <span class="caret"></span>';
+      $attributes['class'][] = 'dropdown';
+      $options['attributes']['class'][] = 'dropdown-toggle';
+      $options['attributes']['data-toggle'] = 'dropdown';
+    }
+  }
+
+  return '<li' . drupal_attributes($attributes) . '>' . l($title, $href, $options) . $sub_menu . "</li>\n";
+}
+
+/**
+ * Overrides theme_menu_link() for book module.
+ */
+function bootstrap_menu_link__book_toc(array $variables) {
+  $element = $variables['element'];
+  $sub_menu = drupal_render($element['#below']);
+
+  $title = $element['#title'];
+  $href = $element['#href'];
+  $options = !empty($element['#localized_options']) ? $element['#localized_options'] : array();
+  $attributes = !empty($element['#attributes']) ? $element['#attributes'] : array();
+  $attributes['role'] = 'presentation';
+
+  // Header.
+  $link = TRUE;
+  if ($title && $href === FALSE) {
+    $attributes['class'][] = 'dropdown-header';
+    $link = FALSE;
+  }
+  // Divider.
+  elseif ($title === FALSE && $href === FALSE) {
+    $attributes['class'][] = 'divider';
+    $link = FALSE;
+  }
+  // Active.
+  elseif (($href == $_GET['q'] || ($href == '<front>' && drupal_is_front_page())) && (empty($options['language']))) {
+    $attributes['class'][] = 'active';
+  }
+
+  // Convert to a link.
+  if ($link) {
+    $title = l($title, $href, $options);
+  }
+  // Otherwise, filter the title if "html" is not set, otherwise l() will
+  // automatically sanitize using check_plain(), so no need to call that here.
+  elseif (empty($options['html'])) {
+    $title = filter_xss_admin($title);
+  }
+
+  return '<li' . drupal_attributes($attributes) . '>' . $title . $sub_menu . "</li>\n";
+}

+ 31 - 0
mydata/themes/bootstrap/templates/menu/menu-link.vars.php

@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "menu_link" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "menu_link" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap_menu_link()
+ * @see theme_menu_link()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_menu_link(array &$variables) {
+  $element = &$variables['element'];
+
+  // Determine if the link should be shown as "active" based on the current
+  // active trail (set by core/contrib modules).
+  // @see https://www.drupal.org/node/2618828
+  // @see https://www.drupal.org/node/1896674
+  if (in_array('active-trail', _bootstrap_get_classes($element)) || ($element['#href'] == '<front>' && drupal_is_front_page())) {
+    $element['#attributes']['class'][] = 'active';
+  }
+}

+ 59 - 0
mydata/themes/bootstrap/templates/menu/menu-local-action.func.php

@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_menu_local_action().
+ */
+
+/**
+ * Returns HTML for a single local action link.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: A render element containing:
+ *     - #link: A menu link array with 'title', 'href', and 'localized_options'
+ *       keys.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_menu_local_action()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_menu_local_action(array $variables) {
+  $link = $variables['element']['#link'];
+
+  $options = isset($link['localized_options']) ? $link['localized_options'] : array();
+
+  // Filter the title if the "html" is set, otherwise l() will automatically
+  // sanitize using check_plain(), so no need to call that here.
+  $title = empty($options['html']) ? filter_xss_admin($link['title']) : $link['title'];
+
+  $icon = _bootstrap_iconize_text($title);
+  $href = !empty($link['href']) ? $link['href'] : FALSE;
+
+  // Format the action link.
+  if ($href) {
+    // Turn link into a mini-button and colorize based on title.
+    if ($class = _bootstrap_colorize_text($title)) {
+      if (!isset($options['attributes']['class'])) {
+        $options['attributes']['class'] = array();
+      }
+      $string = is_string($options['attributes']['class']);
+      if ($string) {
+        $options['attributes']['class'] = explode(' ', $options['attributes']['class']);
+      }
+      $options['attributes']['class'][] = 'btn';
+      $options['attributes']['class'][] = 'btn-xs';
+      $options['attributes']['class'][] = 'btn-' . $class;
+      if ($string) {
+        $options['attributes']['class'] = implode(' ', $options['attributes']['class']);
+      }
+    }
+    // Force HTML so we can render any icon that may have been added.
+    $options['html'] = !empty($options['html']) || !empty($icon) ? TRUE : FALSE;
+  }
+
+  return $href ? l($icon . $title, $href, $options) : $icon . $title;
+}

+ 42 - 0
mydata/themes/bootstrap/templates/menu/menu-local-tasks.func.php

@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_menu_local_tasks().
+ */
+
+/**
+ * Returns HTML for primary and secondary local tasks.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *     - primary: (optional) An array of local tasks (tabs).
+ *     - secondary: (optional) An array of local tasks (tabs).
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_menu_local_tasks()
+ * @see menu_local_tasks()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_menu_local_tasks(array &$variables) {
+  $output = '';
+
+  if (!empty($variables['primary'])) {
+    $variables['primary']['#prefix'] = '<h2 class="element-invisible">' . t('Primary tabs') . '</h2>';
+    $variables['primary']['#prefix'] .= '<ul class="tabs--primary nav nav-tabs">';
+    $variables['primary']['#suffix'] = '</ul>';
+    $output .= drupal_render($variables['primary']);
+  }
+
+  if (!empty($variables['secondary'])) {
+    $variables['secondary']['#prefix'] = '<h2 class="element-invisible">' . t('Secondary tabs') . '</h2>';
+    $variables['secondary']['#prefix'] .= '<ul class="tabs--secondary pagination pagination-sm">';
+    $variables['secondary']['#suffix'] = '</ul>';
+    $output .= drupal_render($variables['secondary']);
+  }
+
+  return $output;
+}

+ 90 - 0
mydata/themes/bootstrap/templates/menu/menu-tree.func.php

@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_menu_tree() and suggestion(s).
+ */
+
+/**
+ * Returns HTML for a wrapper for a menu sub-tree.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see template_preprocess_menu_tree()
+ * @see theme_menu_tree()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_menu_tree(array &$variables) {
+  return '<ul class="menu nav">' . $variables['tree'] . '</ul>';
+}
+
+/**
+ * Bootstrap theme wrapper function for the primary menu links.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @return string
+ *   The constructed HTML.
+ */
+function bootstrap_menu_tree__primary(array &$variables) {
+  return '<ul class="menu nav navbar-nav">' . $variables['tree'] . '</ul>';
+}
+
+/**
+ * Bootstrap theme wrapper function for the secondary menu links.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @return string
+ *   The constructed HTML.
+ */
+function bootstrap_menu_tree__secondary(array &$variables) {
+  return '<ul class="menu nav navbar-nav secondary">' . $variables['tree'] . '</ul>';
+}
+
+/**
+ * Overrides theme_menu_tree() for book module.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @return string
+ *   The constructed HTML.
+ */
+function bootstrap_menu_tree__book_toc(array &$variables) {
+  $output = '<div class="book-toc btn-group pull-right">';
+  $output .= '  <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown">';
+  $output .= t('!icon Outline !caret', array(
+    '!icon' => _bootstrap_icon('list'),
+    '!caret' => '<span class="caret"></span>',
+  ));
+  $output .= '</button>';
+  $output .= '<ul class="dropdown-menu" role="menu">' . $variables['tree'] . '</ul>';
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * Overrides theme_menu_tree() for book module.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @return string
+ *   The constructed HTML.
+ */
+function bootstrap_menu_tree__book_toc__sub_menu(array &$variables) {
+  return '<ul class="dropdown-menu" role="menu">' . $variables['tree'] . '</ul>';
+}

+ 118 - 0
mydata/themes/bootstrap/templates/node/node.tpl.php

@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display a node.
+ *
+ * Available variables:
+ * - $title: the (sanitized) title of the node.
+ * - $content: An array of node items. Use render($content) to print them all,
+ *   or print a subset such as render($content['field_example']). Use
+ *   hide($content['field_example']) to temporarily suppress the printing of a
+ *   given element.
+ * - $user_picture: The node author's picture from user-picture.tpl.php.
+ * - $date: Formatted creation date. Preprocess functions can reformat it by
+ *   calling format_date() with the desired parameters on the $created variable.
+ * - $name: Themed username of node author output from theme_username().
+ * - $node_url: Direct URL of the current node.
+ * - $display_submitted: Whether submission information should be displayed.
+ * - $submitted: Submission information created from $name and $date during
+ *   template_preprocess_node().
+ * - $classes: String of classes that can be used to style contextually through
+ *   CSS. It can be manipulated through the variable $classes_array from
+ *   preprocess functions. The default values can be one or more of the
+ *   following:
+ *   - node: The current template type; for example, "theming hook".
+ *   - node-[type]: The current node type. For example, if the node is a
+ *     "Blog entry" it would result in "node-blog". Note that the machine
+ *     name will often be in a short form of the human readable label.
+ *   - node-teaser: Nodes in teaser form.
+ *   - node-preview: Nodes in preview mode.
+ *   The following are controlled through the node publishing options.
+ *   - node-promoted: Nodes promoted to the front page.
+ *   - node-sticky: Nodes ordered above other non-sticky nodes in teaser
+ *     listings.
+ *   - node-unpublished: Unpublished nodes visible only to administrators.
+ * - $title_prefix (array): An array containing additional output populated by
+ *   modules, intended to be displayed in front of the main title tag that
+ *   appears in the template.
+ * - $title_suffix (array): An array containing additional output populated by
+ *   modules, intended to be displayed after the main title tag that appears in
+ *   the template.
+ *
+ * Other variables:
+ * - $node: Full node object. Contains data that may not be safe.
+ * - $type: Node type; for example, story, page, blog, etc.
+ * - $comment_count: Number of comments attached to the node.
+ * - $uid: User ID of the node author.
+ * - $created: Time the node was published formatted in Unix timestamp.
+ * - $classes_array: Array of html class attribute values. It is flattened
+ *   into a string within the variable $classes.
+ * - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
+ *   teaser listings.
+ * - $id: Position of the node. Increments each time it's output.
+ *
+ * Node status variables:
+ * - $view_mode: View mode; for example, "full", "teaser".
+ * - $teaser: Flag for the teaser state (shortcut for $view_mode == 'teaser').
+ * - $page: Flag for the full page state.
+ * - $promote: Flag for front page promotion state.
+ * - $sticky: Flags for sticky post setting.
+ * - $status: Flag for published status.
+ * - $comment: State of comment settings for the node.
+ * - $readmore: Flags true if the teaser content of the node cannot hold the
+ *   main body content.
+ * - $is_front: Flags true when presented in the front page.
+ * - $logged_in: Flags true when the current user is a logged-in member.
+ * - $is_admin: Flags true when the current user is an administrator.
+ *
+ * Field variables: for each field instance attached to the node a corresponding
+ * variable is defined; for example, $node->body becomes $body. When needing to
+ * access a field's raw values, developers/themers are strongly encouraged to
+ * use these variables. Otherwise they will have to explicitly specify the
+ * desired field language; for example, $node->body['en'], thus overriding any
+ * language negotiation rule that was previously applied.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_node()
+ * @see template_process()
+ *
+ * @ingroup templates
+ */
+?>
+<article id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
+  <?php if ((!$page && !empty($title)) || !empty($title_prefix) || !empty($title_suffix) || $display_submitted): ?>
+  <header>
+    <?php print render($title_prefix); ?>
+    <?php if (!$page && !empty($title)): ?>
+    <h2<?php print $title_attributes; ?>><a href="<?php print $node_url; ?>"><?php print $title; ?></a></h2>
+    <?php endif; ?>
+    <?php print render($title_suffix); ?>
+    <?php if ($display_submitted): ?>
+    <span class="submitted">
+      <?php print $user_picture; ?>
+      <?php print $submitted; ?>
+    </span>
+    <?php endif; ?>
+  </header>
+  <?php endif; ?>
+  <?php
+    // Hide comments, tags, and links now so that we can render them later.
+    hide($content['comments']);
+    hide($content['links']);
+    hide($content['field_tags']);
+    print render($content);
+  ?>
+  <?php
+    // Only display the wrapper div if there are tags or links.
+    $field_tags = render($content['field_tags']);
+    $links = render($content['links']);
+    if ($field_tags || $links):
+  ?>
+   <footer>
+     <?php print $field_tags; ?>
+     <?php print $links; ?>
+  </footer>
+    <?php endif; ?>
+  <?php print render($content['comments']); ?>
+</article>

+ 25 - 0
mydata/themes/bootstrap/templates/picture/image-srcset.vars.php

@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "image_srcset" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "image_srcset" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see theme_image_srcset()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_image_srcset(array &$variables) {
+  // Add image shape, if necessary.
+  if ($shape = bootstrap_setting('image_shape')) {
+    $variables['attributes']['class'][] = $shape;
+  }
+}

+ 22 - 0
mydata/themes/bootstrap/templates/picture/picture.vars.php

@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "picture" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "picture" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @see theme_picture()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_picture(&$variables) {
+  // Add responsiveness, if necessary.
+  if ($shape = bootstrap_setting('image_responsive')) {
+    $variables['attributes']['class'][] = 'img-responsive';
+  }
+}

+ 25 - 0
mydata/themes/bootstrap/templates/poll/poll-bar--block.tpl.php

@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display bar for a single choice in a poll.
+ *
+ * Variables available:
+ * - $title: The title of the poll.
+ * - $votes: The number of votes for this choice
+ * - $total_votes: The number of votes for this choice
+ * - $percentage: The percentage of votes for this choice.
+ * - $vote: The choice number of the current user's vote.
+ * - $voted: Set to TRUE if the user voted for this choice.
+ *
+ * @see template_preprocess_poll_bar()
+ *
+ * @ingroup templates
+ */
+?>
+<div class="text"><?php print $title; ?></div>
+<div class="progress">
+  <div class="progress-bar" role="progressbar" aria-valuenow="<?php print $percentage; ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php print $percentage; ?>%;">
+    <?php print $percentage; ?>%
+  </div>
+</div>

+ 25 - 0
mydata/themes/bootstrap/templates/poll/poll-bar.tpl.php

@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display bar for a single choice in a poll.
+ *
+ * Variables available:
+ * - $title: The title of the poll.
+ * - $votes: The number of votes for this choice
+ * - $total_votes: The number of votes for this choice
+ * - $percentage: The percentage of votes for this choice.
+ * - $vote: The choice number of the current user's vote.
+ * - $voted: Set to TRUE if the user voted for this choice.
+ *
+ * @see template_preprocess_poll_bar()
+ *
+ * @ingroup templates
+ */
+?>
+<div class="text"><?php print $title; ?></div>
+<div class="progress">
+  <div class="progress-bar" role="progressbar" aria-valuenow="<?php print $percentage; ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php print $percentage; ?>%;">
+    <?php print $percentage; ?>% (<?php print format_plural($votes, '1 vote', '@count votes'); ?>)
+  </div>
+</div>

+ 39 - 0
mydata/themes/bootstrap/templates/search/search-block-form.tpl.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Displays the search form block.
+ *
+ * Available variables:
+ * - $search_form: The complete search form ready for print.
+ * - $search: Associative array of search elements. Can be used to print each
+ *   form element separately.
+ *
+ * Default elements within $search:
+ * - $search['search_block_form']: Text input area wrapped in a div.
+ * - $search['actions']: Rendered form buttons.
+ * - $search['hidden']: Hidden form elements. Used to validate forms when
+ *   submitted.
+ *
+ * Modules can add to the search form, so it is recommended to check for their
+ * existence before printing. The default keys will always exist. To check for
+ * a module-provided field, use code like this:
+ * @code
+ *   <?php if (isset($search['extra_field'])): ?>
+ *     <div class="extra-field">
+ *       <?php print $search['extra_field']; ?>
+ *     </div>
+ *   <?php endif; ?>
+ * @endcode
+ *
+ * @see template_preprocess_search_block_form()
+ *
+ * @ingroup templates
+ */
+?>
+<div>
+  <?php if (empty($variables['form']['#block']->subject)): ?>
+    <h2 class="element-invisible"><?php print t('Search form'); ?></h2>
+  <?php endif; ?>
+  <?php print $search_form; ?>
+</div>

+ 45 - 0
mydata/themes/bootstrap/templates/system/breadcrumb.func.php

@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_breadcrumb().
+ */
+
+/**
+ * Returns HTML for a breadcrumb trail.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - breadcrumb: An array containing the breadcrumb links.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_breadcrumb()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_breadcrumb(array $variables) {
+  // Use the Path Breadcrumbs theme function if it should be used instead.
+  if (_bootstrap_use_path_breadcrumbs()) {
+    return path_breadcrumbs_breadcrumb($variables);
+  }
+
+  $output = '';
+  $breadcrumb = $variables['breadcrumb'];
+
+  // Determine if we are to display the breadcrumb.
+  $bootstrap_breadcrumb = bootstrap_setting('breadcrumb');
+  if (($bootstrap_breadcrumb == 1 || ($bootstrap_breadcrumb == 2 && arg(0) == 'admin')) && !empty($breadcrumb)) {
+    $build = array(
+      '#theme' => 'item_list__breadcrumb',
+      '#attributes' => array(
+        'class' => array('breadcrumb'),
+      ),
+      '#items' => $breadcrumb,
+      '#type' => 'ol',
+    );
+    $output = drupal_render($build);
+  }
+  return $output;
+}

+ 47 - 0
mydata/themes/bootstrap/templates/system/breadcrumb.vars.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "breadcrumb" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "breadcrumb" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap_breadcrumb()
+ * @see theme_breadcrumb()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_breadcrumb(array &$variables) {
+  // Do not modify breadcrumbs if the Path Breadcrumbs module should be used.
+  if (_bootstrap_use_path_breadcrumbs()) {
+    return;
+  }
+
+  $breadcrumb = &$variables['breadcrumb'];
+
+  // Optionally get rid of the homepage link.
+  $show_breadcrumb_home = bootstrap_setting('breadcrumb_home');
+  if (!$show_breadcrumb_home) {
+    array_shift($breadcrumb);
+  }
+
+  if (bootstrap_setting('breadcrumb_title') && !empty($breadcrumb)) {
+    $item = menu_get_item();
+
+    $page_title = !empty($item['tab_parent']) ? check_plain($item['title']) : drupal_get_title();
+    if (!empty($page_title)) {
+      $breadcrumb[] = array(
+        // If we are on a non-default tab, use the tab's title.
+        'data' => $page_title,
+        'class' => array('active'),
+      );
+    }
+  }
+}

+ 49 - 0
mydata/themes/bootstrap/templates/system/button.func.php

@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_button().
+ */
+
+/**
+ * Returns HTML for a button form element.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *     Properties used: #attributes, #button_type, #name, #value.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_button()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_button(array $variables) {
+  $element = $variables['element'];
+  $text = $element['#value'];
+
+  // Allow button text to be appear hidden.
+  // @see https://www.drupal.org/node/2327437
+  if (!empty($element['#hide_text']) || $element['#icon_position'] === 'icon_only') {
+    $text = '<span class="sr-only">' . $text . '</span>';
+  }
+
+  // Add icons before or after the value.
+  // @see https://www.drupal.org/node/2219965
+  if (!empty($element['#icon']) && ($icon = render($element['#icon']))) {
+    // Add icon position class.
+    _bootstrap_add_class('icon-' . drupal_html_class($element['#icon_position'] === 'icon_only' ? 'only' : $element['#icon_position']), $element);
+
+    if ($element['#icon_position'] === 'after') {
+      $text .= ' ' . $icon;
+    }
+    else {
+      $text = $icon . ' ' . $text;
+    }
+  }
+
+  // This line break adds inherent margin between multiple buttons.
+  return '<button' . drupal_attributes($element['#attributes']) . '>' . filter_xss_admin($text) . "</button>\n";
+}

+ 50 - 0
mydata/themes/bootstrap/templates/system/button.vars.php

@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Stub file for "button" theme hook [pre]process functions.
+ */
+
+/**
+ * Pre-processes variables for the "button" theme hook.
+ *
+ * See theme function for list of available variables.
+ *
+ * @param array $variables
+ *   An associative array of variables, passed by reference.
+ *
+ * @see bootstrap_button()
+ * @see theme_button()
+ *
+ * @ingroup theme_preprocess
+ */
+function bootstrap_preprocess_button(array &$variables) {
+  $element = &$variables['element'];
+
+  // Drupal buttons should be of type 'submit'.
+  // @see https://www.drupal.org/node/2540452
+  $element['#attributes']['type'] = 'submit';
+
+  // Set the element's other attributes.
+  element_set_attributes($element, array('id', 'name', 'value'));
+
+  // Add the base Bootstrap button class.
+  $element['#attributes']['class'][] = 'btn';
+
+  // Add button size, if necessary.
+  if ($size = bootstrap_setting('button_size')) {
+    $element['#attributes']['class'][] = $size;
+  }
+
+  // Colorize button.
+  _bootstrap_colorize_button($element);
+
+  // Iconize button.
+  _bootstrap_iconize_button($element);
+
+  // Add in the button type class.
+  $element['#attributes']['class'][] = 'form-' . $element['#button_type'];
+
+  // Ensure that all classes are unique, no need for duplicates.
+  $element['#attributes']['class'] = array_unique($element['#attributes']['class']);
+}

+ 50 - 0
mydata/themes/bootstrap/templates/system/container.func.php

@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_container().
+ */
+
+/**
+ * Returns HTML to wrap child elements in a container.
+ *
+ * Used for grouped form items. Can also be used as a #theme_wrapper for any
+ * renderable element, to surround it with a <div> and add attributes such as
+ * classes or an HTML id.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *     Properties used: #id, #attributes, #children.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_container()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_container(array $variables) {
+  $element = $variables['element'];
+
+  // Ensure #attributes is set.
+  $element += array('#attributes' => array());
+
+  // Special handling for form elements.
+  if (isset($element['#array_parents'])) {
+    // Assign an html ID.
+    if (!isset($element['#attributes']['id'])) {
+      $element['#attributes']['id'] = $element['#id'];
+    }
+
+    // Core's "form-wrapper" class is required for states.js to function.
+    $element['#attributes']['class'][] = 'form-wrapper';
+
+    // Add Bootstrap "form-group" class.
+    if (!isset($element['#form_group']) || !!$element['#form_group']) {
+      $element['#attributes']['class'][] = 'form-group';
+    }
+  }
+
+  return '<div' . drupal_attributes($element['#attributes']) . '>' . $element['#children'] . '</div>';
+}

+ 37 - 0
mydata/themes/bootstrap/templates/system/date.func.php

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_date().
+ */
+
+/**
+ * Returns HTML for a date selection form element.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *     Properties used: #title, #value, #options, #description, #required,
+ *     #attributes.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_date()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_date(array $variables) {
+  $element = $variables['element'];
+
+  $attributes = array();
+  if (isset($element['#id'])) {
+    $attributes['id'] = $element['#id'];
+  }
+  if (!empty($element['#attributes']['class'])) {
+    $attributes['class'] = (array) $element['#attributes']['class'];
+  }
+  $attributes['class'][] = 'form-inline';
+
+  return '<div' . drupal_attributes($attributes) . '>' . drupal_render_children($element) . '</div>';
+}

+ 47 - 0
mydata/themes/bootstrap/templates/system/exposed-filters.func.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_exposed_filters().
+ */
+
+/**
+ * Returns HTML for an exposed filter form.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - form: An associative array containing the structure of the form.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_exposed_filters()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_exposed_filters(array $variables) {
+  $form = $variables['form'];
+  $output = '';
+
+  foreach (element_children($form['status']['filters']) as $key) {
+    $form['status']['filters'][$key]['#field_prefix'] = '<div class="col-sm-10">';
+    $form['status']['filters'][$key]['#field_suffix'] = '</div>';
+  }
+  $form['status']['actions']['#attributes']['class'][] = 'col-sm-offset-2';
+  $form['status']['actions']['#attributes']['class'][] = 'col-sm-10';
+
+  if (isset($form['current'])) {
+    $items = array();
+    foreach (element_children($form['current']) as $key) {
+      $items[] = drupal_render($form['current'][$key]);
+    }
+    $build = array(
+      '#theme' => 'item_list',
+      '#items' => $items,
+      '#attributes' => array('class' => array('clearfix', 'current-filters')),
+    );
+    $output .= drupal_render($build);
+  }
+  $output .= drupal_render_children($form);
+  return '<div class="form-horizontal">' . $output . '</div>';
+}

+ 29 - 0
mydata/themes/bootstrap/templates/system/fieldset.func.php

@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Stub file for bootstrap_fieldset().
+ */
+
+/* @noinspection PhpDocMissingThrowsInspection */
+
+/**
+ * Returns HTML for a fieldset form element and its children.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *     Properties used: #attributes, #children, #collapsed, #collapsible,
+ *     #description, #id, #title, #value.
+ *
+ * @return string
+ *   The constructed HTML.
+ *
+ * @see theme_fieldset()
+ *
+ * @ingroup theme_functions
+ */
+function bootstrap_fieldset(array $variables) {
+  /* @noinspection PhpUnhandledExceptionInspection */
+  return theme('bootstrap_panel', $variables);
+}

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff