From: Steve Sutton
Date: Thu, 4 Sep 2014 19:10:47 +0000 (-0400)
Subject: add headway
X-Git-Url: http://cvs2.gaslightmedia.com/gitweb/index.cgi?a=commitdiff_plain;h=69b0a289f23b875958d2c5626dcc4625aa246d5b;p=web%2FPetoskeyRobotics.git
add headway
---
diff --git a/wp-content/themes/headway/README.txt b/wp-content/themes/headway/README.txt
new file mode 100644
index 0000000..d9209b9
--- /dev/null
+++ b/wp-content/themes/headway/README.txt
@@ -0,0 +1,10 @@
+Headway Base Installation
+http://headwaythemes.com/
+
+INSTALL:
+1. Upload Headway Base via FTP to your wp-content/themes/ directory.
+2. Go to your WordPress dashboard and select Appearance.
+3. Select Headway Base and click activate.
+
+SUPPORT & DOCUMENTATION:
+If you are looking for detailed documentation or theme support, please visit http://support.headwaythemes.com/
\ No newline at end of file
diff --git a/wp-content/themes/headway/docs/license.txt b/wp-content/themes/headway/docs/license.txt
new file mode 100644
index 0000000..0f780dc
--- /dev/null
+++ b/wp-content/themes/headway/docs/license.txt
@@ -0,0 +1,281 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110, 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 Library 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
+
diff --git a/wp-content/themes/headway/docs/terms_of_service.txt b/wp-content/themes/headway/docs/terms_of_service.txt
new file mode 100644
index 0000000..9268c55
--- /dev/null
+++ b/wp-content/themes/headway/docs/terms_of_service.txt
@@ -0,0 +1,152 @@
+TERMS & CONDITIONS
+
+This End User License Agreement is a binding legal agreement between you and Vesped, Inc, d/b/a Headway Themes, LLC (Company). Purchase, installation or use of Headway Themes (Service) provided on HeadwayThemes.com signifies that you have read, understood, and agreed to be bound by the terms outlined below.
+
+1. HEADWAY THEMES LICENSING
+
+HEADWAY THEMES GPL LICENSING
+
+All WordPress themes produced by Headway Themes, LLC (Company) are released under the GPL version 2.0 license (http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2).
+
+THEME DELIVERY
+
+After your payment has been successfully received, you will receive download links and support forum registration information to the email address you provided during purchase. If you do not receive an email after this time period, contact at support@headwaythemes.com
+
+
+2. TERMS OF SERVICE FOR MEMBERSHIP
+
+A. SIMPLE VERSION
+
+As a paid customer of the Service, you are a member of the HeadwayThemes.com website community. This allows you to get upgraded versions of Headway Themes, support in the forums, quick access to new products, and other benefits of membership, all subject to the terms and conditions contained in this document.
+
+HEADWAY BASE:
+
+The Headway Base Plan entitles you access to Headway Members only support and product updates for a period of one (1) year. You may use Headway Base on an unlimited number of domains. You may remove the footer attribution linking to headwaythemes.com if you want.
+
+HEADWAY STANDARD:
+
+The Headway Standard Plan entitles you access to Headway Members only support and product updates for a period of one (1) year. You may use Headway Standard on an unlimited number of domains. You may remove the footer attribution linking to headwaythemes.com if you want. You also get access to 3 Headway Child Themes during your year of membership.
+
+HEADWAY ALL-ACCESS:
+
+The Headway All-Access Plan entitles you access to Headway Members only support and product updates for a period of one (1) year. You may use Headway All-Access on an unlimited number of domains. You may remove the footer attribution linking to headwaythemes.com if you want. You also get access to all Headway Child Themes during your year of membership. With the All-Access plan you also have access to early beta releases and exclusive developer webinars.
+
+* For the above plans, you get access to updates and support for a period of one (1) year. At that time you will be required to renew your membership to receive product updates and support for another year.
+
+HEADWAY LIFETIME PASS:
+
+The Headway Lifetime Pass Plan entitles you access to Headway Members only support and product updates for life. You may use Headway Lifetime Pass Plan on an unlimited number of domains. You may remove the footer attribution linking to headwaythemes.com if you want. You also get access to all Headway Child Themes released. With the All-Access plan you also have access to early beta releases and exclusive developer webinars.
+
+* Access to product updates and support is for lifetime.
+
+Use or distribution of Headway Themes in violation of the terms and conditions of membership contained in this document will result in termination of your membership, without refund. Also, please be civil and considerate when making use of the support forums, as bad behavior is also grounds for termination of your membership.
+
+B. LEGAL STUFF
+
+Use and enjoyment of services ("Service") from Headway Themes, LLC ("Headway Themes, LLC"), owned and operated by Vesped, Inc, d/b/a Headway Themes, LLC, is provided to you ("you" or "Member") under the Headway Themes Membership Terms and Conditions of Service ("Terms and Conditions of Service" or "Agreement").
+
+Headway Themes, LLC reserves the right to update and change the Terms and Conditions of Service from time to time without notice. Any new features that augment or enhance the current Service, including the release of new features and resources, shall be subject to the Terms and Conditions of Service. Continued use of the Service after any such changes shall constitute your consent to such changes. Members can review the most current version of the Terms and Conditions of Service at any time at this URL: http://headwaythemes.com/terms_of_service.txt
+
+Violation of any of the terms below will result in the termination of your Membership. You agree to use the Service at your own risk.
+
+MEMBERSHIP AND ACCOUNT TERMS
+
+HeadwayThemes.com is a membership website. Use of enjoyment of Membership benefits, such as product access, updates, support, training and other benefits of Membership are provided to paid Members in good standing only. You are responsible for updating your information, including contact names, addresses, telephone numbers and credit card information (as applicable) in a timely manner.
+
+* Members must be 18 years or older to use this Service.
+
+* Members are responsible for maintaining the security of accounts and passwords. Headway Themes, LLC cannot and will not be liable for any loss or damage from your failure to comply with this security obligation.
+
+* Members are responsible for all Content posted and activity that occurs under your account.
+
+* Members may not use the Service for any illegal or unauthorized purpose. You must not, in the use of the Service, violate any laws in your jurisdiction (including but not limited to copyright and trademark laws).
+
+LICENSE, ACKNOWLEDGMENTS AND WARRANTIES
+
+Headway Themes (Service) Members submitting content in forums grant Headway Themes, LLC the rights to distribute, display, reproduce, reformat, translate, archive, license, edit, modify and create derivative works and/or excerpts of any such material for purposes of distributing the material as part of Company's products and services (and the promotion of same).
+
+No Member Content submitted by Member shall contain any content that is obscene, libelous, slanderous or otherwise defamatory, false or misleading or which violates any copyright, right of privacy or publicity or other right of any person, and the Member Content will not contain any viruses, scripts, macros, or programs or links to macros, scripts, programs, or any code that alters, destroys or inhibits the operation of, or infiltrates, computer systems or data run through such computer systems. Member shall indemnify and hold harmless Headway Themes, LLC, its affiliates and agents, and those licensed or otherwise authorized by Headway Themes, LLC to process, transmit or distribute Member Content from and against any and all claims, losses, damages, liabilities, costs and expenses (including reasonable attorney's fees) arising out of or relating to any breach by Member of the foregoing representations and warranties or otherwise arising out of or relating to the contents or nature of the Member Content.
+
+MODIFICATION TO THE SERVICE AND PRICES
+
+Headway Themes, LLC reserves the right at any time and from time to time to modify or discontinue, temporarily or permanently, the Service (or any part thereof) with or without notice.
+
+Prices of all Services, including but not limited to upgrade packages and membership fees, are subject to change at anytime.
+
+Headway Themes, LLC shall not be liable to you or to any third party for any modification, price change, suspension or discontinuance of the Service.
+
+PAYMENTS AND REFUNDS
+
+Payment - A valid credit card or PayPal account is required for purchasing upgrades or additional products or services.
+
+Refunds - Headway Themes, LLC does not offer refunds.
+
+TERM
+
+Term of membership, with the exception of the Headway Lifetime Pass, is for a period of one year from date of purchase as long as Member continues to use Headway Themes, LLC services, or until such time as either party notifies the other to terminate with or without cause. These Terms and Conditions, including any revisions, remain in effect for the duration of membership.
+
+Term of membership for Headway Lifetime Pass is perpetual from date of purchase as long as Member continues to use Headway Themes, LLC services, or until such time as either party notifies the other to terminate with or without cause. These Terms and Conditions, including any revisions, remain in effect for the duration of membership.
+
+ACCESS
+
+During the Term, you are authorized to access the Service solely to manage your Headway Themes member account(s) or as otherwise authorized by Headway Themes, LLC in writing. You agree that you will not use the Service or any content therein or data obtained there from for any other purpose and that you will not disseminate any of this information. Your right to access your account with the Service (including, without limitation, any login or other access information) is personal to you, non-transferable and non-assignable, and is subject to any limits established by Headway Themes, LLC. You agree that you will not use any automated means, including, without limitation, agents, robots, scripts, or spiders, to access or manage your account with the Service or to monitor or copy the Service websites or the content contained therein except those automated means expressly made available by Headway Themes, LLC, if any, or authorized in advance and in writing by Headway Themes, LLC (for example, Headway Themes-approved third party tools and services). Without limitation to the foregoing, you further agree that you will not take any action that imposes an unreasonable or disproportionately large load on the Service as determined by Headway Themes, LLC.
+
+INDEMNITY AND LIMITATION OF LIABILITY
+
+Member will indemnify and hold harmless Headway Themes, LLC and its, affiliate and subsidiary companies, officers, directors, employees, licensees, successors and assigns, including those licensed or authorized by Headway Themes, LLC to transmit and distribute materials, from any and all liabilities, damages, judgments, claims, costs, losses, and expenses (including reasonable legal fees and costs) arising out of or related to any and all claims alleging conduct that would amount to a breach of any of Company's representations and warranties in the Membership Agreement, including these Terms and Conditions.
+
+HEADWAY THEMES, LLC SHALL NOT BE LIABLE TO MEMBER FOR ANY INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL OR EXEMPLARY DAMAGES (EVEN IF HEADWAY THEMES, LLC HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES), ARISING FROM OR RELATED IN ANY WAY TO ANY PROVISION OF THIS AGREEMENT (INCLUDING SUCH DAMAGES INCURRED BY THIRD PARTIES), INCLUDING BUT NOT LIMITED TO LOSS OF REVENUE OR ANTICIPATED PROFITS OR LOST BUSINESS. IN NO EVENT SHALL HEADWAY THEMES BE LIABLE TO MEMBER FOR AN AMOUNT GREATER THAN THE PAYMENTS MADE BY MEMBER TO HEADWAY THEMES, LLC FOR PRODUCTS AND SERVICES PROVIDED PURSUANT TO THE TERMS OF THIS AGREEMENT. Some jurisdictions do not allow the exclusion of liability for incidental or consequential damages, so some or all of the above exclusions or limitations may not apply.
+
+CANCELLATION AND TERMINATION
+
+Headway Themes, LLC, in its sole discretion, has the right to suspend or terminate your account and refuse any and all current or future use of the Service, or any other Headway Themes, LLC service, for violation of these Member Terms of Service. Such termination of the Service will result in the deactivation or deletion of your Account or your access to your Account, and the forfeiture and relinquishment of all content in your account. Headway Themes, LLC reserves the right to refuse service to anyone for any reason at any time, and to refund your payment and terminate your account in the sole discretion of Headway Themes, LLC.
+
+If Member is dissatisfied with any aspect of the Service(s), your sole and exclusive remedy is to terminate the Agreement and/or the Service(s) Terms by requesting your account be closed.
+
+Reasons for Headway Themes, LLC's determination to so terminate, suspend or discontinue your account or participation may include, but is not limited to, if Headway Themes, LLC believes that you violated the Agreement or other policies or guidelines of the Service, a Third Party Product, or if Headway Themes, LLC believes Member conduct may be harmful to other consumers, members or licensees who participate in (or offer to its users) the Service Web Sites (and/or any part thereof).
+
+All decisions made by Headway Themes, LLC in this matter will be final and neither Headway Themes, LLC nor any of the Headway Themes, LLC Entities shall have any liability regarding such decisions.
+
+MAJEURE
+
+If Service is prevented or delayed in or from performing any of its obligations under the Agreement due to circumstances beyond its control, including but not limited to governmental acts, war, riots, strikes or trade disputes (including by and with our own employees), technical failure, general availability of the internet, power failure, communications failure, weather, flood, fire or explosion, natural or local emergency, Headway Themes, LLC shall not be liable for any resulting failure to provide services hereunder.
+
+NOTICES
+
+Any notices or communications under the agreement shall be by electronic mail or in writing and shall be deemed delivered upon receipt to the party to whom such communication is directed, at the addresses specified below. If to Headway Themes, LLC, such notices shall be addressed to support@headwaythemes.com or to Grant Griffiths, Headway Themes, LLC, 513 Prospect Street, Clay Center, Kansas 67432 , USA. If to Member, such notices shall be addressed to the electronic or mailing address specified in Members's service registration form, or such other address as either party may give the other by notice as provided in this section. It is the applicant's responsibility to provide an accurate address and to ensure that the Service is notified of any changes to applicant's address as specified in this section.
+
+GOVERNING LAW, VENUE AND ATTORNEYS FEES
+
+The Membership Agreement, including these Terms and Conditions, shall be governed by and construed in accordance with the laws of the United States and the State of Kansas. Any dispute arising under or related in any way to this Agreement shall be adjudicated in a court of competent jurisdiction in the County of Clay, Kansas. In the event of litigation to enforce any provision of the Membership Agreement, including these Terms and Conditions, the prevailing party will be entitled to recover from the other party its costs and fees, including reasonable legal fees.
+
+ELECTRONIC SIGNATURES EFFECTIVE
+
+The Agreement is an electronic contract that sets out the legally binding terms of your use of the Service's products and services, including, without limitation, the Service Web Sites. You indicate your acceptance of the Agreement and all of the terms and conditions contained or referenced in the Agreement and these Member Terms of Service and in any Programs Terms by clicking on the "I Accept" button in connection with your enrollment. This action creates an electronic signature that has the same legal force and effect as a handwritten signature. By clicking on the "I Accept" button, you accept the Agreement, including, without limitation, the Programs Terms and agree to the terms, conditions and notices contained or referenced therein. When you click on the "I Accept" button during enrollment, you also consent to have the Agreement provided to you in electronic form. You have the right to receive the Agreement in non-electronic form.
+
+In order to access and retain this electronic Agreement, you must have access to the World Wide Web, either directly or through devices that access web-based content, and pay any service fees associated with such access. In addition, you must use all equipment necessary to make such connection to the World Wide Web, including, without limitation, a computer and modem or other access device. Please print a copy of the Agreement for your records. To retain an electronic copy of the Agreement, you may save it into any word processing program. We will notify you of any changes in the hardware or software requirements needed to access and/or retain the Agreement that create a material risk that you will not be able to continue to access and/or retain the electronic Agreement.
+
+TRADEMARK INFORMATION
+
+All logos, product, and service name related to these TOS are trademarks of Headway Themes, LLC. Without Headway Themes, LLC's prior permission, you agree not to display or use in any manner the Headway Themes Trademarks.
+
+3. GENERAL CONDITIONS
+
+* Each Member uses the Service at Member's sole risk. The Service is provided on an "as is" and "as available" basis.
+Technical support is only available via the support forum
+
+* Member must not use any Headway Themes, LLC digital products in a manner not permitted by the terms of Member's membership level, and must not distribute any Headway Themes, LLC digital products to third parties by any means, including but not limited to posting download links at public or private forums, websites, peer-to-peer networks, torrents, or email lists. With the exception to those as authorized by the GPL version 2.0 license (http://www.gnu.org/licenses/gpl-2.0.htmlÃÂ GNU/GPLv2). Headway Themes, LLC reserves all rights with respect to its intellectual property, and all remedies, in law and in equity.
+
+* Member must not modify, adapt or hack the Service or modify another website so as to falsely imply that it is associated with the Service, Headway Themes, LLC, or any other Headway Themes, LLC service.
+
+* Member agree not to reproduce, duplicate, copy, sell, resell or exploit any portion of the Service, use of the Service, or access to the Service without the express written permission by Headway Themes, LLC. With the exception to those as authorized by the GPL version 2.0 license (http://www.gnu.org/licenses/gpl-2.0.htmlÃÂ GNU/GPLv2).
+Headway Themes, LLC may, but has no obligation to, remove Content and Accounts containing Content that we determine in our sole discretion are unlawful, offensive, threatening, libelous, defamatory, pornographic, obscene or otherwise objectionable or violates any party's intellectual property or these Terms of Service.
+
+* Verbal, physical, written or other abuse (including threats of abuse or retribution) of any Headway Themes, LLC customer, employee, member, or officer will result in immediate account termination.
+
+* Headway Themes, LLC does not warrant that (i) the service will meet your specific requirements, (ii) the service will be uninterrupted, timely, secure, or error-free, (iii) the results that may be obtained from the use of the service will be accurate or reliable, (iv) the quality of any products, services, information, or other material purchased or obtained by you through the service will meet your expectations, and (v) any errors in the Service will be corrected.
+
+* Member expressly understands and agrees that Headway Themes, LLC shall not be liable for any direct, indirect, incidental, special, consequential or exemplary damages, including but not limited to, damages for loss of profits, goodwill, use, data or other intangible losses (even if Headway Themes, LLC has been advised of the possibility of such damages), resulting from: (i) the use or the inability to use the Service; (ii) the cost of procurement of substitute goods and services resulting from any goods, data, information or services purchased or obtained or messages received or transactions entered into through or from the service; (iii) unauthorized access to or alteration of your transmissions or data; (iv) statements or conduct of any third party on the service; (v) or any other matter relating to the service. Headway Themes, LLCââ¬â¢s liability to you shall not, for any reason, exceed the amount actually paid by you to Headway Themes, LLC.
+
+* The failure of Headway Themes, LLC to exercise or enforce any right or provision of the Terms of Service shall not constitute a waiver of such right or provision. The Terms of Service constitutes the entire agreement between you and Headway Themes, LLC and govern your use of the Service, superseding any prior agreements between you and Headway Themes, LLC (including, but not limited to, any prior versions of the Terms of Service).
+
+Effective Date December 1st, 2011
diff --git a/wp-content/themes/headway/footer.php b/wp-content/themes/headway/footer.php
new file mode 100644
index 0000000..2c1949e
--- /dev/null
+++ b/wp-content/themes/headway/footer.php
@@ -0,0 +1,11 @@
+add_menu(array(
+ 'id' => 'headway',
+ 'title' => 'Headway',
+ 'href' => add_query_arg(array('visual-editor' => 'true', 'visual-editor-mode' => $default_visual_editor_mode, 've-layout' => HeadwayLayout::get_current()), home_url())
+ ));
+
+ //Visual Editor
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway',
+ 'id' => 'headway-ve',
+ 'title' => 'Visual Editor',
+ 'href' => add_query_arg(array('visual-editor' => 'true', 'visual-editor-mode' => $default_visual_editor_mode, 've-layout' => HeadwayLayout::get_current()), home_url())
+ ));
+
+ //Grid
+ if ( current_theme_supports('headway-grid') ) {
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-ve',
+ 'id' => 'headway-ve-grid',
+ 'title' => 'Grid',
+ 'href' => add_query_arg(array('visual-editor' => 'true', 'visual-editor-mode' => 'grid', 've-layout' => HeadwayLayout::get_current()), home_url())
+ ));
+
+ }
+
+ //Design Editor
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-ve',
+ 'id' => 'headway-ve-design',
+ 'title' => 'Design',
+ 'href' => add_query_arg(array('visual-editor' => 'true', 'visual-editor-mode' => 'design', 've-layout' => HeadwayLayout::get_current()), home_url())
+ ));
+
+ //Templates
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway',
+ 'id' => 'headway-admin-templates',
+ 'title' => 'Templates',
+ 'href' => admin_url('admin.php?page=headway-templates')
+ ));
+
+ //Admin Options
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway',
+ 'id' => 'headway-admin-options',
+ 'title' => 'Options',
+ 'href' => admin_url('admin.php?page=headway-options')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-options',
+ 'id' => 'headway-admin-options-general',
+ 'title' => 'General',
+ 'href' => admin_url('admin.php?page=headway-options#tab-general')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-options',
+ 'id' => 'headway-admin-options-seo',
+ 'title' => 'Search Engine Optimization',
+ 'href' => admin_url('admin.php?page=headway-options#tab-seo')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-options',
+ 'id' => 'headway-admin-options-scripts',
+ 'title' => 'Scripts/Analytics',
+ 'href' => admin_url('admin.php?page=headway-options#tab-scripts')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-options',
+ 'id' => 'headway-admin-options-visual-editor',
+ 'title' => 'Visual Editor',
+ 'href' => admin_url('admin.php?page=headway-options#tab-visual-editor')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-options',
+ 'id' => 'headway-admin-options-advanced',
+ 'title' => 'Advanced',
+ 'href' => admin_url('admin.php?page=headway-options#tab-advanced')
+ ));
+
+ //Admin Tools
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway',
+ 'id' => 'headway-admin-tools',
+ 'title' => 'Tools',
+ 'href' => admin_url('admin.php?page=headway-tools')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-tools',
+ 'id' => 'headway-admin-tools-system-info',
+ 'title' => 'System Info',
+ 'href' => admin_url('admin.php?page=headway-tools#tab-system-info')
+ ));
+
+ $wp_admin_bar->add_menu(array(
+ 'parent' => 'headway-admin-tools',
+ 'id' => 'headway-admin-tools-reset',
+ 'title' => 'Reset',
+ 'href' => admin_url('admin.php?page=headway-tools#tab-reset')
+ ));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/admin-meta-boxes.php b/wp-content/themes/headway/library/admin/admin-meta-boxes.php
new file mode 100644
index 0000000..d1ebe67
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/admin-meta-boxes.php
@@ -0,0 +1,291 @@
+ array(
+ 'id' => 'template',
+ 'type' => 'select',
+ 'options' => array(),
+ 'description' => 'Assign a shared layout to this entry. Shared layouts can be added and modified in the Headway Visual Editor.',
+ 'blank-option' => '– Do Not Use Shared Layout –'
+ )
+ );
+
+ protected function modify_arguments($post = false) {
+
+ $this->inputs['template']['options'] = HeadwayLayout::get_templates();
+
+ $post_type = get_post_type_object( $post->post_type );
+
+ $this->inputs['template']['description'] = str_replace('entry', strtolower($post_type->labels->singular_name), $this->inputs['template']['description']);
+
+ }
+
+}
+
+headway_register_admin_meta_box('HeadwayMetaBoxTitleControl');
+class HeadwayMetaBoxTitleControl extends HeadwayAdminMetaBoxAPI {
+
+ protected $id = 'alternate-title';
+
+ protected $name = 'Title Control';
+
+ protected $context = 'side';
+
+ protected $inputs = array(
+ 'hide-title' => array(
+ 'id' => 'hide-title',
+ 'name' => 'Hide Title',
+ 'type' => 'select',
+ 'blank-option' => '– Do Not Hide Title –',
+ 'options' => array(
+ 'singular' => 'Hide on Single View',
+ 'list' => 'Hide in Index and Archives',
+ 'both' => 'Hide on Single View, Index, and Archives'
+ ),
+ 'description' => 'Choose whether or not you would like to hide the title for this entry. This can be useful if you have advanced formatting in this entry.',
+ ),
+
+ 'alternate-title' => array(
+ 'id' => 'alternate-title',
+ 'name' => 'Alternate Title',
+ 'type' => 'text',
+ 'description' => 'Using the alternate page title, you can override the title that\'s displayed in the Content Block of the page. Doing this, you can have a shorter page title in the navigation menu and <title>, but have a longer and more descriptive title in the actual page content.'
+ )
+ );
+
+}
+
+
+headway_register_admin_meta_box('HeadwayMetaBoxDisplay');
+class HeadwayMetaBoxDisplay extends HeadwayAdminMetaBoxAPI {
+
+ protected $id = 'display';
+
+ protected $name = 'Display';
+
+ protected $inputs = array(
+ 'css-class' => array(
+ 'id' => 'css-class',
+ 'name' => 'Custom CSS Class(es)',
+ 'type' => 'text',
+ 'description' => 'If you are familiar with CSS and would like to style this entry by targeting a certain CSS class (or classes), then you may enter them in here. The class will be added to the entry container\'s class along with the body class if only this entry is being viewed (e.g. single post or page view). Classes can be separated with spaces and/or commas.'
+ )
+ );
+
+}
+
+
+headway_register_admin_meta_box('HeadwayMetaBoxPostThumbnail');
+class HeadwayMetaBoxPostThumbnail extends HeadwayAdminMetaBoxAPI {
+
+ protected $id = 'post-thumbnail';
+
+ protected $name = 'Featured Image Position';
+
+ protected $context = 'side';
+
+ protected $priority = 'low';
+
+ protected $inputs = array(
+ 'position' => array(
+ 'id' => 'position',
+ 'name' => 'Featured Image Position',
+ 'type' => 'radio',
+ 'options' => array(
+ '' => 'Use Block Default',
+ 'left' => 'Left',
+ 'right' => 'Right',
+ 'above-title' => 'Above Title',
+ 'above-content' => 'Above Content'
+ ),
+ 'description' => 'Set the position of the featured image for this entry.',
+ 'default' => '',
+ 'group' => 'post-thumbnail'
+ ),
+ );
+
+}
+
+
+if ( !HeadwaySEO::plugin_active() )
+ headway_register_admin_meta_box('HeadwayMetaBoxSEO');
+class HeadwayMetaBoxSEO extends HeadwayAdminMetaBoxAPI {
+
+ protected $id = 'seo';
+
+ protected $name = 'Search Engine Optimization (SEO)';
+
+ protected $post_type_supports_id = 'headway-seo';
+
+ protected $priority = 'high';
+
+ protected $inputs = array(
+ 'seo-preview' => array(
+ 'id' => 'seo-preview',
+ 'type' => 'seo-preview'
+ ),
+
+ 'title' => array(
+ 'id' => 'title',
+ 'group' => 'seo',
+ 'name' => 'Title',
+ 'type' => 'text',
+ 'description' => 'Custom <title> tag'
+ ),
+
+ 'description' => array(
+ 'id' => 'description',
+ 'group' => 'seo',
+ 'name' => 'Description',
+ 'type' => 'textarea',
+ 'description' => 'Custom <meta> description'
+ ),
+
+ 'noindex' => array(
+ 'id' => 'noindex',
+ 'group' => 'seo',
+ 'name' => 'noindex this entry.',
+ 'type' => 'checkbox',
+ 'description' => 'Index/NoIndex tells the engines whether the entry should be crawled and kept in the engines\' index for retrieval. If you check this box to opt for noindex, the entry will be excluded from the engines. Note: if you\'re not sure what this does, do not check this box.'
+ ),
+
+ 'nofollow' => array(
+ 'id' => 'nofollow',
+ 'group' => 'seo',
+ 'name' => 'nofollow links in this entry.',
+ 'type' => 'checkbox',
+ 'description' => 'Follow/NoFollow tells the engines whether links on the entry should be crawled. If you check this box to employ "nofollow," the engines will disregard the links on the entry both for discovery and ranking purposes. Note: if you\'re not sure what this does, do not check this box.'
+ ),
+
+ 'noarchive' => array(
+ 'id' => 'noarchive',
+ 'group' => 'seo',
+ 'name' => 'noarchive links in this entry.',
+ 'type' => 'checkbox',
+ 'description' => 'Noarchive is used to restrict search engines from saving a cached copy of the entry. By default, the engines will maintain visible copies of all pages they indexed, accessible to searchers through the "cached" link in the search results. Check this box to restrict search engines from storing cached copies of this entry.'
+ ),
+
+ 'nosnippet' => array(
+ 'id' => 'nosnippet',
+ 'group' => 'seo',
+ 'name' => 'nosnippet links in this entry.',
+ 'type' => 'checkbox',
+ 'description' => 'Nosnippet informs the engines that they should refrain from displaying a descriptive block of text next to the entry\'s title and URL in the search results.'
+ ),
+
+ 'noodp' => array(
+ 'id' => 'noodp',
+ 'group' => 'seo',
+ 'name' => 'noodp links in this entry.',
+ 'type' => 'checkbox',
+ 'description' => 'NoODP is a specialized tag telling the engines not to grab a descriptive snippet about a page from the Open Directory Project (DMOZ) for display in the search results.'
+ ),
+
+ 'noydir' => array(
+ 'id' => 'noydir',
+ 'group' => 'seo',
+ 'name' => 'noydir links in this entry.',
+ 'type' => 'checkbox',
+ 'description' => 'NoYDir, like NoODP, is specific to Yahoo!, informing that engine not to use the Yahoo! Directory description of a page/site in the search results.'
+ ),
+
+ 'redirect-301' => array(
+ 'id' => 'redirect-301',
+ 'group' => 'seo',
+ 'name' => '301 Permanent Redirect',
+ 'type' => 'text',
+ 'description' => 'The 301 Permanent Redirect can be used to forward an old post or page to a new or different location. If you ever move a page or change a page\'s permalink, use this to forward your visitors to the new location.
';
+
+ echo 'Remember, this is only a predicted search engine result preview. There is no guarantee that it will look exactly this way. However, it will look similar.';
+
+ }
+
+
+ protected function input_text_with_counter($input) {
+
+ echo '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 130
+
+
+ ';
+
+ }
+
+
+ protected function modify_arguments($post = false) {
+
+ //Do not use this box if the page being edited is the front page since they can edit the setting in the configuration.
+ if ( get_option('page_on_front') == headway_get('post') && get_option('show_on_front') == 'page' ) {
+
+ $this->info = 'Configure the SEO settings for this page (Front Page) in the Headway Search Engine Optimization settings tab in Headway » Configuration.';
+
+ $this->inputs = array();
+
+ return;
+
+ }
+
+ //Setup the defaults for the title and checkboxes
+ $current_screen = get_current_screen();
+ $seo_templates_query = HeadwayOption::get('seo-templates', 'general', HeadwaySEO::output_layouts_and_defaults());
+ $seo_templates = headway_get('single-' . $current_screen->id, $seo_templates_query, array());
+
+ $title_template = str_replace(array('%sitename%', '%SITENAME%'), get_bloginfo('name'), headway_get('title', $seo_templates));
+
+ echo '';
+
+ $this->inputs['noindex']['default'] = headway_get('noindex', $seo_templates);
+ $this->inputs['nofollow']['default'] = headway_get('nofollow', $seo_templates);
+ $this->inputs['noarchive']['default'] = headway_get('noarchive', $seo_templates);
+ $this->inputs['nosnippet']['default'] = headway_get('nosnippet', $seo_templates);
+ $this->inputs['noodp']['default'] = headway_get('noodp', $seo_templates);
+ $this->inputs['noydir']['default'] = headway_get('noydir', $seo_templates);
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/admin-pages.php b/wp-content/themes/headway/library/admin/admin-pages.php
new file mode 100644
index 0000000..4340f0b
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/admin-pages.php
@@ -0,0 +1,71 @@
+You are now being redirected. If you are not redirected within 3 seconds, click here.
';
+ echo '';
+ HeadwayAdmin::show_footer();
+
+ }
+
+
+ public static function getting_started() {
+
+ HeadwayAdmin::show_header();
+
+ require_once HEADWAY_LIBRARY_DIR . '/admin/pages/getting-started.php';
+
+ HeadwayAdmin::show_footer();
+
+ }
+
+
+ public static function whats_new() {
+
+ require_once HEADWAY_LIBRARY_DIR . '/admin/pages/whats-new.php';
+
+ }
+
+
+ public static function templates() {
+
+ HeadwayAdmin::show_header();
+
+ require_once HEADWAY_LIBRARY_DIR . '/admin/pages/templates.php';
+
+ HeadwayAdmin::show_footer();
+
+ }
+
+
+ public static function options() {
+
+ HeadwayAdmin::show_header();
+
+ require_once HEADWAY_LIBRARY_DIR . '/admin/pages/options.php';
+
+ HeadwayAdmin::show_footer();
+
+ }
+
+
+ public static function tools() {
+
+ HeadwayAdmin::show_header();
+
+ require_once HEADWAY_LIBRARY_DIR . '/admin/pages/tools.php';
+
+ HeadwayAdmin::show_footer();
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/admin-write.php b/wp-content/themes/headway/library/admin/admin-write.php
new file mode 100644
index 0000000..54a77f3
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/admin-write.php
@@ -0,0 +1,62 @@
+post_type == 'revision' )
+ return false;
+
+ /* Figure out the layout ID */
+ $layout_id = 'single-' . $post->post_type . '-' . $postid;
+
+ /* Delete everything from the layout including blocks, wrapper, design editor instances, and the wp_options rows */
+ HeadwayLayout::delete_layout($layout_id, false);
+
+ }
+
+
+ public static function open_in_visual_editor_button($return, $id, $new_title, $new_slug) {
+
+ global $post;
+
+ if ( !isset($post->ID) || !is_numeric($post->ID) || $post->post_status != 'publish' || !HeadwayCapabilities::can_user_visually_edit() )
+ return $return;
+
+ $layout_id = 'single' . HeadwayLayout::$sep . $post->post_type . HeadwayLayout::$sep . $post->ID;
+
+ if ( get_option('show_on_front') === 'page' ) {
+
+ if ( $post->ID == get_option('page_on_front') )
+ $layout_id = 'front_page';
+
+ if ( $post->ID == get_option('page_for_posts') )
+ $layout_id = 'index';
+
+ }
+
+ $visual_editor_url = home_url('/?visual-editor=true&ve-layout=' . urlencode($layout_id));
+
+ $return .= 'Open in Visual Editor';
+
+ return $return;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/admin.php b/wp-content/themes/headway/library/admin/admin.php
new file mode 100644
index 0000000..6b962e0
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/admin.php
@@ -0,0 +1,613 @@
+ true,
+ 'admin/admin-pages',
+ 'admin/api-admin-inputs'
+ ));
+
+ }
+
+
+ public static function setup_hooks() {
+
+ /* Actions */
+ add_action('admin_init', array(__CLASS__, 'activation'), 1);
+ add_action('admin_init', array(__CLASS__, 'enqueue'));
+ add_action('admin_init', array(__CLASS__, 'visual_editor_redirect'), 12);
+
+ add_action('init', array(__CLASS__, 'form_action_save'), 12); // Init runs before admin_menu; admin_menu runs before admin_init
+ add_action('init', array(__CLASS__, 'form_action_licenses'), 12);
+ add_action('init', array(__CLASS__, 'form_action_reset'), 12);
+
+ add_action('admin_menu', array(__CLASS__, 'add_menus'));
+ add_action('admin_head', array(__CLASS__, 'remove_system_submenus'));
+
+ add_action('headway_admin_save_message', array(__CLASS__, 'save_message'));
+ add_action('headway_admin_save_error_message', array(__CLASS__, 'save_error_message'));
+
+ add_action('admin_notices', array(__CLASS__, 'notice_no_widgets_or_menus'));
+
+ add_filter('page_row_actions', array(__CLASS__, 'row_action_visual_editor'), 10, 2);
+ add_filter('post_row_actions', array(__CLASS__, 'row_action_visual_editor'), 10, 2);
+ add_filter('tag_row_actions', array(__CLASS__, 'row_action_visual_editor'), 10, 2);
+
+ }
+
+
+ public static function form_action_save() {
+
+ //Form action for all Headway configuration panels. Not in function/hook so it can load before everything else.
+ if ( !headway_post('headway-submit', false))
+ return false;
+
+ if ( !wp_verify_nonce(headway_post('headway-admin-nonce', false), 'headway-admin-nonce') ) {
+
+ global $headway_admin_save_message;
+ $headway_admin_save_message = 'Security nonce did not match.';
+
+ return false;
+
+ }
+
+ foreach ( headway_post('headway-admin-input', array()) as $option => $value ) {
+
+ HeadwayOption::set($option, $value);
+
+ }
+
+ global $headway_admin_save_message;
+ $headway_admin_save_message = 'Settings saved.';
+
+ return true;
+
+ }
+
+
+ public static function form_action_licenses() {
+
+ if ( !headway_post('headway-licenses', false))
+ return false;
+
+ if ( !wp_verify_nonce(headway_post('headway-admin-nonce', false), 'headway-admin-nonce') )
+ return false;
+
+ if ( !is_array(headway_post('headway-licenses')) )
+ return false;
+
+ global $headway_admin_save_message;
+ global $headway_admin_save_error_message;
+
+
+ /* Save and activations */
+ if ( $save_and_activations = headway_get('save-and-activate', headway_post('headway-licenses')) ) {
+
+ if ( is_array($save_and_activations) && count($save_and_activations) ) {
+
+ foreach ( $save_and_activations as $item_slug_to_activate => $submit_value ) {
+
+ HeadwayOption::set('license-key-' . $item_slug_to_activate, headway_get('license-key-' . $item_slug_to_activate, headway_post('headway-admin-input')));
+ $activation_request = headway_activate_license($item_slug_to_activate);
+
+ self::set_license_activation_message($activation_request);
+
+ }
+
+ }
+
+ }
+
+ /* Activations */
+ if ( $activations = headway_get('activate', headway_post('headway-licenses')) ) {
+
+ if ( is_array($activations) && count($activations) ) {
+
+ foreach ( headway_get('activate', headway_post('headway-licenses')) as $item_slug_to_activate => $submit_value ) {
+
+ $activation_request = headway_activate_license($item_slug_to_activate);
+
+ self::set_license_activation_message($activation_request);
+
+ }
+
+ }
+
+ }
+
+ /* Deactivations */
+ if ( $deactivations = headway_get('deactivate', headway_post('headway-licenses')) ) {
+
+ if ( is_array($deactivations) && count($deactivations) ) {
+
+ foreach ( headway_get('deactivate', headway_post('headway-licenses')) as $item_slug_to_deactivate => $submit_value ) {
+
+ $deactivation_request = headway_deactivate_license($item_slug_to_deactivate);
+
+ if ( $deactivation_request == 'deactivated' ) {
+
+ $headway_admin_save_message = 'License deactivated.';
+
+ } else if ( !is_wp_error($deactivation_request) ) {
+
+ $headway_admin_save_error_message = 'Whoops! Could not deactivate license. Please check that you have entered your license correctly.';
+
+ } else {
+
+ $headway_admin_save_error_message = '
+ Error While Deactivating: (' . $deactivation_request->get_error_code() . ') ' . $deactivation_request->get_error_message() . '
+ ' . __('Please contact Headway Support if this error persists.', 'headway') . '
+ ';
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ return true;
+
+ }
+
+
+ public static function set_license_activation_message($activation_request) {
+
+ global $headway_admin_save_message;
+ global $headway_admin_save_error_message;
+
+ if ( $activation_request == 'active' || $activation_request == 'valid' ) {
+
+ $headway_admin_save_message = __('License saved and activated.', 'headway');
+
+ } else if ( $activation_request == 'invalid' || $activation_request == 'expired' ) {
+
+ $headway_admin_save_error_message = __('
+ Whoops! Could not activate license. Please check that you have entered your license correctly and that it has not expired.
+ Make sure you copied your license correctly from the Headway Dashboard.
+ ', 'headway');
+
+ } else if ( is_wp_error($activation_request) ) {
+
+ $headway_admin_save_error_message = '
+ Error While Activating: (' . $activation_request->get_error_code() . ') ' . $activation_request->get_error_message() . '
+ ' . __('Please contact Headway Support if this error persists.', 'headway') . '
+ ';
+
+ }
+
+ }
+
+
+ public static function form_action_reset() {
+
+ global $wpdb;
+
+ if ( !defined('HEADWAY_ALLOW_RESET') || HEADWAY_ALLOW_RESET !== true )
+ return false;
+
+ //Form action for all Headway configuration panels. Not in function/hook so it can load before everything else.
+ if ( !headway_post('reset-headway', false) )
+ return false;
+
+ //Verify the nonce so other sites can't maliciously reset a Headway installation.
+ if ( !wp_verify_nonce(headway_post('headway-reset-nonce', false), 'headway-reset-nonce') ) {
+
+ $GLOBALS['headway_admin_save_message'] = 'Security nonce did not match.';
+
+ return false;
+
+ }
+
+ /* Loop through WordPress options and delete the skin options */
+ $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name = 'headway'" );
+ $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'headway_%'" );
+
+ $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_hw_%'" );
+
+ /* Remove Headway post meta */
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key LIKE '_hw_%'" );
+
+ /* Drop Headway tables */
+ Headway::mysql_drop_tables();
+
+ /* Flush WP cache */
+ wp_cache_flush();
+
+ do_action('headway_global_reset');
+
+ $GLOBALS['headway_admin_save_message'] = 'Headway was successfully reset.';
+
+ //This will hide the reset box if set to true.
+ $GLOBALS['headway_reset_success'] = true;
+
+ return true;
+
+ }
+
+
+ public static function activation() {
+
+ if ( !is_admin() || !headway_get('activated') )
+ return false;
+
+ global $pagenow;
+
+ if ( $pagenow !== 'themes.php' )
+ return false;
+
+ //Since they may be upgrading and files may change, let's clear the cache
+ do_action('headway_activation');
+
+ self::activation_redirect();
+
+ }
+
+
+ public static function activation_redirect() {
+
+ do_action('headway_activation_redirect');
+
+ //If a child theme has been activated rather than Headway, then don't redirect.
+ //Let the child theme developer redirect if they want by using the hook above.
+ if ( HEADWAY_CHILD_THEME_ACTIVE === true )
+ return false;
+
+ $parent_menu = self::parent_menu();
+
+ //If header were sent, then don't do the redirect
+ if ( headers_sent() )
+ return false;
+
+ //We're all good, redirect now
+ wp_safe_redirect(admin_url('admin.php?page=headway-' . $parent_menu['id']));
+ die();
+
+ }
+
+
+ public static function visual_editor_redirect() {
+
+ if ( isset($_GET['page']) && strpos($_GET['page'], 'headway-visual-editor') !== false && !headers_sent() )
+ wp_safe_redirect(home_url() . '/?visual-editor=true');
+
+ }
+
+
+ public static function add_admin_separator($position){
+
+ global $menu;
+
+ $menu[$position] = array('', 'read', 'separator-headway', '', 'wp-menu-separator headway-separator');
+
+ ksort($menu);
+
+ }
+
+
+ public static function add_admin_submenu($name, $id, $callback) {
+
+ $parent_menu = self::parent_menu();
+
+ return add_submenu_page('headway-' . $parent_menu['id'], $name, $name, 'manage_options', $id, $callback);
+
+ }
+
+
+ public static function add_menus(){
+
+ //If the hide menus constant is set to true, don't hide the menus!
+ if (defined('HEADWAY_HIDE_MENUS') && HEADWAY_HIDE_MENUS === true)
+ return false;
+
+ //If user cannot access the admin panels, then don't bother running these functions
+ if ( !HeadwayCapabilities::can_user_visually_edit() )
+ return false;
+
+ $menu_name = ( HeadwayOption::get('hide-menu-version-number', false, true) == true ) ? 'Headway' : 'Headway ' . HEADWAY_VERSION;
+
+ $icon = (version_compare($GLOBALS['wp_version'], '3.8', '>=') && get_user_option('admin_color') != 'light') ? 'headway-32-white.png' : 'headway-16.png';
+ $icon_url = headway_url() . '/library/admin/images/' . $icon;
+
+ $parent_menu = self::parent_menu();
+
+ self::add_admin_separator(48);
+
+ add_menu_page($parent_menu['name'], $menu_name, 'manage_options', 'headway-' . $parent_menu['id'], $parent_menu['callback'], $icon_url, 49);
+
+ switch ( $parent_menu['id'] ) {
+
+ case 'getting-started':
+ self::add_admin_submenu('Getting Started', 'headway-getting-started', array('HeadwayAdminPages', 'getting_started'));
+ self::add_admin_submenu('Visual Editor', 'headway-visual-editor', array('HeadwayAdminPages', 'visual_editor'));
+
+ self::add_admin_submenu('Templates', 'headway-templates', array('HeadwayAdminPages', 'templates'));
+ self::add_admin_submenu('Options', 'headway-options', array('HeadwayAdminPages', 'options'));
+ self::add_admin_submenu('Tools', 'headway-tools', array('HeadwayAdminPages', 'tools'));
+ break;
+
+ case 'visual-editor':
+ self::add_admin_submenu('Visual Editor', 'headway-visual-editor', array('HeadwayAdminPages', 'visual_editor'));
+
+ self::add_admin_submenu('Templates', 'headway-templates', array('HeadwayAdminPages', 'templates'));
+ self::add_admin_submenu('Options', 'headway-options', array('HeadwayAdminPages', 'options'));
+ self::add_admin_submenu('Tools', 'headway-tools', array('HeadwayAdminPages', 'tools'));
+ break;
+
+ case 'options':
+ self::add_admin_submenu('Options', 'headway-options', array('HeadwayAdminPages', 'options'));
+ self::add_admin_submenu('Visual Editor', 'headway-visual-editor', array('HeadwayAdminPages', 'visual_editor'));
+ self::add_admin_submenu('Templates', 'headway-templates', array('HeadwayAdminPages', 'templates'));
+ self::add_admin_submenu('Tools', 'headway-tools', array('HeadwayAdminPages', 'tools'));
+ break;
+
+ }
+
+ self::add_admin_submenu( 'What\'s New', 'headway-whats-new', array( 'HeadwayAdminPages', 'whats_new' ) );
+
+ }
+
+
+ public static function remove_system_submenus() {
+
+ $parent_menu = HeadwayAdmin::parent_menu();
+
+ remove_submenu_page( 'headway-' . $parent_menu['id'], 'headway-whats-new' );
+
+ }
+
+
+ public static function parent_menu() {
+
+ $menu_setup = HeadwayOption::get('menu-setup', false, 'getting-started');
+
+ /* Figure out the primary page */
+ switch ( $menu_setup ) {
+
+ case 'getting-started':
+ $parent_menu = array(
+ 'id' => 'getting-started',
+ 'name' => 'Getting Started',
+ 'callback' => array('HeadwayAdminPages', 'getting_started')
+ );
+ break;
+
+ case 'visual-editor':
+ $parent_menu = array(
+ 'id' => 'visual-editor',
+ 'name' => 'Visual Editor',
+ 'callback' => array('HeadwayAdminPages', 'visual_editor')
+ );
+ break;
+
+ case 'options':
+ $parent_menu = array(
+ 'id' => 'options',
+ 'name' => 'Options',
+ 'callback' => array('HeadwayAdminPages', 'options')
+ );
+ break;
+
+ }
+
+ return $parent_menu;
+
+ }
+
+
+ public static function enqueue() {
+
+ global $pagenow;
+
+ /* Scripts Path */
+ $script_folder = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? 'scripts' : 'scripts-min';
+
+ /* Global */
+ wp_enqueue_style('headway_admin_global', headway_url() . '/library/admin/css/admin-headway-global.css');
+
+ /* General Headway admin CSS/JS */
+ if ( strpos(headway_get('page'), 'headway') !== false ) {
+
+ wp_enqueue_script('headway_jquery_scrollto', headway_url() . '/library/admin/js/jquery.scrollto.js', array('jquery'));
+ wp_enqueue_script('headway_jquery_tabby', headway_url() . '/library/admin/js/jquery.tabby.js', array('jquery'));
+ wp_enqueue_script('headway_jquery_qtip', headway_url() . '/library/admin/js/jquery.qtip.js', array('jquery'));
+ wp_enqueue_script('headway_admin_js', headway_url() . '/library/admin/js/admin-headway.js', array('jquery', 'headway_jquery_qtip'));
+
+ wp_enqueue_style('headway_admin', headway_url() . '/library/admin/css/admin-headway.css');
+ wp_enqueue_style('headway_alerts', headway_url() . '/library/media/css/alerts.css');
+
+ }
+
+ /* Templates */
+ if ( headway_get('page') == 'headway-templates' ) {
+
+ wp_enqueue_script('headway_knockout', headway_url() . '/library/admin/js/knockout.js', array('jquery'));
+ wp_enqueue_script('headway_admin_templates', headway_url() . '/library/admin/js/admin-templates.js', array('jquery'));
+
+ wp_localize_script('headway_admin_templates', 'Headway', array(
+ 'ajaxURL' => admin_url('admin-ajax.php'),
+ 'security' => wp_create_nonce('headway-visual-editor-ajax'),
+
+ 'templates' => HeadwayTemplates::get_all(),
+ 'templateActive' => HeadwayTemplates::get_active(),
+
+ 'viewModels' => array()
+ ));
+
+ add_thickbox();
+ wp_enqueue_media();
+
+ }
+
+ /* Meta Boxes */
+ wp_enqueue_style('headway_admin_write', headway_url() . '/library/admin/css/admin-write.css');
+ wp_enqueue_style('headway_alerts', headway_url() . '/library/media/css/alerts.css');
+ wp_enqueue_script('headway_admin_write', headway_url() . '/library/admin/js/admin-write.js', array('jquery'));
+
+ /* Auto Updater */
+ if ( $pagenow === 'update-core.php' ) {
+
+ wp_enqueue_script('headway_admin', headway_url() . '/library/admin/js/admin-headway.js', array('jquery'));
+ wp_enqueue_style('headway_admin', headway_url() . '/library/admin/css/admin-headway.css');
+ wp_enqueue_style('headway_alerts', headway_url() . '/library/media/css/alerts.css');
+
+ }
+
+ }
+
+
+ public static function save_message() {
+
+ global $headway_admin_save_message;
+
+ if ( !isset($headway_admin_save_message) || $headway_admin_save_message == false )
+ return false;
+
+ echo '
' . $headway_admin_save_message . '
';
+
+ }
+
+
+ public static function save_error_message() {
+
+ global $headway_admin_save_error_message;
+
+ if ( !isset($headway_admin_save_error_message) || $headway_admin_save_error_message == false )
+ return false;
+
+ echo '
' . $headway_admin_save_error_message . '
';
+
+ }
+
+
+ public static function notice_no_widgets_or_menus() {
+
+ global $pagenow;
+
+ if ( $pagenow != 'widgets.php' && $pagenow != 'nav-menus.php' )
+ return false;
+
+ $grid_mode_url = add_query_arg(array('visual-editor' => 'true', 'visual-editor-mode' => 'grid'), home_url());
+
+ //Show the widgets message if no widget blocks exist.
+ if ( $pagenow == 'widgets.php' ) {
+
+ $widget_area_blocks = HeadwayBlocksData::get_blocks_by_type('widget-area');
+
+ if ( !empty($widget_area_blocks) )
+ return;
+
+ if ( !current_theme_supports('headway-grid') )
+ return;
+
+ echo '
+
Headway has detected that you have no Widget Area blocks. If you wish to use the WordPress widgets system with Headway, please add a Widget Area block in the Visual Editor: Grid.
+
+
+
';
+
+ }
+
+ //Show the navigation menus message if no navigation blocks exist.
+ if ( $pagenow == 'nav-menus.php' ) {
+
+ $navigation_blocks = HeadwayBlocksData::get_blocks_by_type('navigation');
+
+ if ( !empty($navigation_blocks) )
+ return;
+
+ if ( !current_theme_supports('headway-grid') )
+ return;
+
+ echo '
+
Headway has detected that you have no Navigation blocks. If you wish to use the WordPress menus system with Headway, please add a Navigation block in the Visual Editor: Grid.
');
+
+ notification.appendTo('#headway-admin-notifications');
+
+ return notification;
+
+ }
+
+ updateNotification = function(id, message) {
+
+ return $('#headway-notification-' + id).children('p').html(message);
+
+ }
+
+ hideNotification = function(id) {
+
+ $('#headway-notification-' + id).fadeOut(500);
+
+ }
+
+
+ var templates = {
+ init: function() {
+
+ templates.bind();
+ templates.setupViewModel();
+
+ },
+
+ setupViewModel: function() {
+
+ Headway.viewModels.templates = {
+ templates: ko.observableArray(Headway.templates),
+ active: ko.observable(Headway.templateActive),
+ activateSkin: function() {
+
+ var skin = this;
+
+ /* Don't try to activate if it's already activated */
+ if ( skin.id == Headway.viewModels.templates.active().id )
+ return;
+
+ /* Send AJAX Request to switch skins */
+ $.post(Headway.ajaxURL, {
+ security: Headway.security,
+ action: 'headway_visual_editor',
+ method: 'switch_skin',
+ skin: skin.id
+ }, function(response) {
+
+ /* Set this skin as the activated skin */
+ Headway.viewModels.templates.active(skin);
+
+ showNotification({
+ id: 'skin-switched',
+ message: skin.name + ' activated.',
+ closeTimer: 5000,
+ success: true
+ });
+
+ });
+
+ },
+ deleteSkin: function() {
+
+ var skin = this;
+
+ if ( !confirm('Are you sure you want to delete this template? All design settings, blocks, and layout settings for this template will be deleted.') )
+ return;
+
+ /* Send AJAX Request to switch skins */
+ $.post(Headway.ajaxURL, {
+ security: Headway.security,
+ action: 'headway_visual_editor',
+ method: 'delete_skin',
+ skin: skin.id
+ }, function(response) {
+
+ if ( response != 'success' ) {
+
+ return showErrorNotification({
+ id: 'unable-to-delete-skin',
+ message: 'Unable to delete template.',
+ });
+
+ } else {
+
+ showNotification({
+ id: 'skin-deleted',
+ message: skin.name + ' deleted.',
+ closeTimer: 5000,
+ success: true
+ });
+
+ }
+
+ Headway.viewModels.templates.templates.remove(skin);
+
+ });
+
+ }
+ }
+
+ ko.applyBindings(Headway.viewModels.templates, $('.headway-templates').get(0));
+
+ },
+
+ bind: function() {
+
+ /* Skin Upload button */
+ $('#install-template').on('click', function() {
+
+ if ( $(this).is('[disabled]') )
+ return;
+
+ $('#upload-skin input[type="file"]').first().trigger('click');
+
+ });
+
+
+ $('#upload-skin input[type="file"]').on('change', function(event) {
+
+ if ( event.target.files[0].name.split('.').slice(-1)[0] != 'json' )
+ return alert("Invalid template.\n\nPlease make sure that you have unzipped the Headway Template. You should be uploading a .json file.");
+
+ var skinFile = $(this).get(0).files[0];
+
+ if ( skinFile && typeof skinFile.name != 'undefined' && typeof skinFile.type != 'undefined' ) {
+
+ var skinReader = new FileReader();
+
+ skinReader.onload = function(e) {
+
+ var skinJSON = e.target.result;
+ var skin = JSON.parse(skinJSON);
+
+ /* Check to be sure that the JSON file is a layout */
+ if ( skin['data-type'] != 'skin' )
+ return alert('Cannot load template. Please insure that the file is a valid Headway Template.');
+
+ /* Deactivate install template button */
+ $('#install-template').attr('disabled', 'true');
+
+ showNotification({
+ id: 'installing-skin',
+ message: 'Installing Template: ' + skin['name'],
+ closeTimer: false,
+ closable: false
+ });
+
+ Headway.viewModels.templates.templates.push({
+ description: null,
+ name: 'Installing ' + skin['name'] + '...',
+ installing: true,
+ id: null,
+ author: null,
+ active: false,
+ version: null
+ });
+
+ installSkin(skin);
+
+ }
+
+ skinReader.readAsText(skinFile);
+
+ } else {
+
+ alert('Cannot load template. Please insure that the file is a valid Headway Template.');
+
+ }
+
+ });
+
+
+ installSkin = function(skin) {
+
+ if ( typeof skin['image-definitions'] == 'object' && Object.keys(skin['image-definitions']).length ) {
+
+ var numberOfImages = Object.keys(skin['image-definitions']).length;
+ var importedImages = {};
+
+ showNotification({
+ id: 'skin-importing-images',
+ message: 'Importing Images...',
+ closeTimer: false,
+ closable: false
+ });
+
+ var importSkinImage = function(imageID) {
+
+ /* Update notification for image import */
+ var imageIDInt = parseInt(imageID.replace('%%', '').replace('IMAGE_REPLACEMENT_', ''));
+
+ updateNotification('skin-importing-images', 'Importing Image (' + imageIDInt + '/' + numberOfImages + ')');
+
+ /* Do the AJAX request to upload the image */
+ var imageImportXhr = $.post(Headway.ajaxURL, {
+ security: Headway.security,
+ action: 'headway_visual_editor',
+ method: 'import_image',
+ imageID: imageID,
+ imageContents: skin['image-definitions'][imageID]
+ }, null, 'json')
+ .always(function(response) {
+
+ /* Update notification */
+
+ /* Check if error. If so, fire notification */
+ if ( typeof response['url'] == 'undefined' ) {
+ var response = 'ERROR';
+
+ showNotification({
+ id: 'skin-importing-images-error-' + imageIDInt,
+ message: 'Error Importing Image #' + imageIDInt,
+ closeTimer: 10000,
+ closable: true,
+ error: true
+ });
+ }
+
+ /* Store uploaded image URL */
+ importedImages[imageID] = response;
+
+ /* Check if there are more images to upload. If so, upload them. */
+ var nextImageID = '%%IMAGE_REPLACEMENT_' + (parseInt(imageID.replace('%%', '').replace('IMAGE_REPLACEMENT_', '')) + 1) + '%%';
+
+ if ( typeof skin['image-definitions'][nextImageID] != 'undefined' ) {
+
+ importSkinImage(nextImageID);
+
+ /* If not, finalize skin installation */
+ } else {
+
+ /* Hide notification since images are uploaded is complete */
+ hideNotification('skin-importing-images');
+
+ /* Finalize */
+ skin['imported-images'] = importedImages;
+
+ finalizeSkinInstallation(skin);
+
+ }
+
+ });
+ /* End doing AJAX request to upload image */
+
+ }
+
+ importSkinImage('%%IMAGE_REPLACEMENT_1%%');
+
+ } else {
+
+ finalizeSkinInstallation(skin);
+
+ }
+
+ }
+
+
+ finalizeSkinInstallation = function(skin) {
+
+ /* Remove image definitions from skin array since they've already been imported */
+ if ( typeof skin['image-definitions'] != 'undefined' )
+ delete skin['image-definitions'];
+
+ /* Do AJAX request to install skin */
+ return $.post(Headway.ajaxURL, {
+ security: Headway.security,
+ action: 'headway_visual_editor',
+ method: 'install_skin',
+ skin: JSON.stringify(skin)
+ }).done(function(data) {
+
+ var skin = data;
+
+ if ( typeof skin['error'] !== 'undefined' || typeof skin['name'] == 'undefined' ) {
+
+ if ( typeof skin['error'] == 'undefined' )
+ skin['error'] = 'Could not install template.';
+
+ return showNotification({
+ id: 'skin-not-installed',
+ message: 'Error: ' + skin['error'],
+ closable: true,
+ closeTimer: false,
+ error: true
+ });
+
+ }
+
+ hideNotification('installing-skin');
+
+ showNotification({
+ id: 'skin-installed',
+ message: skin['name'] + ' successfully installed.',
+ closeTimer: 5000,
+ success: true
+ });
+
+ /* Pop off the last skin which is going to be the loader */
+ Headway.viewModels.templates.templates.pop();
+ Headway.viewModels.templates.templates.push($.extend({}, {description: null}, skin));
+
+ /* Reactive install template button */
+ $('#install-template').removeAttr('disabled');
+
+ }).fail(function(data) {
+
+ showNotification({
+ id: 'skin-not-installed',
+ message: 'Error: Could not install template.',
+ closable: true,
+ closeTimer: false,
+ error: true
+ });
+
+ });
+
+ }
+
+ /* Skin Export */
+ $('#export-template-submit').on('click', function(event) {
+
+ event.preventDefault();
+
+ var params = {
+ 'security': Headway.security,
+ 'action': 'headway_visual_editor',
+ 'method': 'export_skin',
+ 'skin-info': $('#export-template-form').serialize()
+ }
+
+ var exportURL = Headway.ajaxURL + '?' + $.param(params);
+
+ return window.open(exportURL);
+
+ });
+
+ /* Export Template Image */
+ var HWTemplateExportImageFrame;
+
+ $('#template-export-image-button').on('click', function (event) {
+
+ event.preventDefault();
+
+ // If the media frame already exists, reopen it.
+ if (HWTemplateExportImageFrame) {
+ HWTemplateExportImageFrame.open();
+ return;
+ }
+
+ // Create the media frame.
+ HWTemplateExportImageFrame = wp.media.frames.file_frame = wp.media({
+ title: 'Select Image for Template',
+ button: {
+ text: 'Select Image',
+ },
+ multiple: false
+ });
+
+ // When an image is selected, run a callback.
+ HWTemplateExportImageFrame.on('select', function () {
+ attachment = HWTemplateExportImageFrame.state().get('selection').first().toJSON();
+
+ $('input#template-export-image').val(attachment.url);
+
+ $('img#template-export-image-preview')
+ .attr('src', attachment.url)
+ .show();
+
+ });
+
+ HWTemplateExportImageFrame.open();
+ });
+
+
+ /* Add Blank Skin */
+ $('#add-blank-template').on('click', function() {
+
+ var skinName = window.prompt('Please enter a name for the new template:' , 'Template Name');
+
+ if ( !skinName || $('#notification-adding-blank-skin').length )
+ return;
+
+ /* Perform AJAX request to create the skin and get the ID and name */
+ $.post(Headway.ajaxURL, {
+ security: Headway.security,
+ action: 'headway_visual_editor',
+ method: 'add_blank_skin',
+ skinName: skinName
+ }, function(response) {
+
+ var skinID = response['id'];
+ var skinName = response['name'];
+
+ showNotification({
+ id: 'added-blank-skin',
+ message: skinName + ' successfully added.',
+ closeTimer: 5000,
+ success: true
+ });
+
+ Headway.viewModels.templates.templates.push({
+ id: skinID,
+ name: skinName,
+ version: null,
+ author: null,
+ description: null
+ });
+
+ }, 'json');
+
+ });
+
+ }
+ }
+
+ templates.init();
+
+});
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/js/admin-write.js b/wp-content/themes/headway/library/admin/js/admin-write.js
new file mode 100644
index 0000000..d7ec413
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/js/admin-write.js
@@ -0,0 +1,140 @@
+(function($) {
+$(document).ready(function() {
+
+ /* SEO Live Preview */
+ if ( $('div#seo-preview').length == 1 ) {
+
+ //Insert content into preview
+ if ( $('textarea#headway-admin-meta-box-seo-description').val().length > 0 ) {
+
+ var description = $('textarea#headway-admin-meta-box-seo-description').val();
+
+ if(description.length > 150){
+ description = description.substr(0, 150) + ' ...';
+ }
+
+ $('div#seo-preview p#seo-preview-description span#text').text(description);
+
+ } else {
+
+ var excerpt = $('textarea#content').val().replace(/(<([^>]+)>)/ig, '');
+
+ if ( excerpt.length > 150 ) {
+ excerpt = excerpt.substr(0, 150) + ' ...';
+ }
+
+ $('div#seo-preview p#seo-preview-description span#text').text(excerpt);
+
+ }
+
+ if ( $('input#headway-admin-meta-box-seo-title').val().length > 0 ) {
+
+ $('div#seo-preview h4').text($('input#headway-admin-meta-box-seo-title').val());
+
+ } else if ( $('div#titlediv input#title').val().length > 0 ) {
+
+ $('div#seo-preview h4').text($('input#title-seo-template').val().replace('%title%', $('div#titlediv input#title').val()));
+
+ }
+
+ if ( $('span#seo-preview-url').text().length == 0 ) {
+
+ $('span#seo-preview-url').text($('span#sample-permalink').text().replace('http://', ''));
+
+ }
+
+ //Bind Inputs
+ $('input#headway-admin-meta-box-seo-title').bind('keyup blur', function() {
+
+ if ( $(this).val().length > 0 ) {
+
+ $('div#seo-preview h4').text($(this).val());
+
+ } else {
+
+ $('div#seo-preview h4').text($('input#title-seo-template').val().replace('%title%', $('div#titlediv input#title').val()));
+
+ }
+
+ });
+
+ $('textarea#headway-admin-meta-box-seo-description').bind('keyup blur', function() {
+
+ var description = $(this).val();
+
+ if ( description.length > 150 )
+ description = description.substr(0, 150) + ' ...';
+
+ if ( $(this).val().length == 0 ) {
+
+ var description = $('textarea#content').val().replace(/(<([^>]+)>)/ig, '');
+
+ if ( excerpt.length > 150 ) {
+ description = excerpt.substr(0, 150) + ' ...';
+ }
+
+ }
+
+ $('div#seo-preview p#seo-preview-description span#text').text(description);
+
+ });
+
+ $('div#titlediv input#title').bind('keyup blur', function() {
+
+ if ( $('input#headway-admin-meta-box-seo-title').val().length == 0 ) {
+
+ $('div#seo-preview h4').text($('input#title-seo-template').val().replace('%title%', $(this).val()));
+
+ }
+
+ });
+
+ //Periodically check for updates in the content
+ setInterval(function() {
+
+ if ( $('textarea#headway-admin-meta-box-seo-description').val().length > 0 )
+ return false;
+
+ if ( $('textarea#content').val() != undefined ){
+ var excerpt = $('textarea#content').val().replace(/(<([^>]+)>)/ig, '');
+ } else {
+ var excerpt = $('textarea#excerpt').val();
+ }
+
+ if ( excerpt.length > 150 )
+ excerpt = excerpt.substr(0, 150) + ' ...';
+
+ $('div#seo-preview p#seo-preview-description span#text').text(excerpt);
+
+ }, 4000);
+
+ //Bind Clickables
+ $('div#seo-preview h4').bind('click', function(event) {
+
+ if ( $('input#headway-admin-meta-box-seo-title').val().length == 0 )
+ $('input#headway-admin-meta-box-seo-title').val($(this).text());
+
+ $('input#headway-admin-meta-box-seo-title')
+ .focus()
+ .css({backgroundColor: '#FFF6BF'})
+ .animate({backgroundColor: '#fff'}, 400);
+
+ event.preventDefault();
+
+ });
+
+ $('div#seo-preview p#seo-preview-description').bind('click', function(event) {
+
+ $('textarea#headway-admin-meta-box-seo-description')
+ .focus()
+ .css({backgroundColor: '#FFF6BF'})
+ .animate({backgroundColor: '#fff'}, 400);
+
+ event.preventDefault();
+
+ });
+ }
+ /* End SEO Live Preview */
+
+});
+})(jQuery);
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/js/jquery.masonry.js b/wp-content/themes/headway/library/admin/js/jquery.masonry.js
new file mode 100644
index 0000000..f0da370
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/js/jquery.masonry.js
@@ -0,0 +1,9 @@
+/*!
+ * Masonry PACKAGED v3.1.5
+ * Cascading grid layout library
+ * http://masonry.desandro.com
+ * MIT License
+ * by David DeSandro
+ */
+
+!function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}return this.each(function(){var d=a.data(this,b);d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d))})}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;"function"==typeof define&&define.amd?define("jquery-bridget/jquery.bridget",["jquery"],c):c(a.jQuery)}(window),function(a){function b(b){var c=a.event;return c.target=c.target||c.srcElement||b,c}var c=document.documentElement,d=function(){};c.addEventListener?d=function(a,b,c){a.addEventListener(b,c,!1)}:c.attachEvent&&(d=function(a,c,d){a[c+d]=d.handleEvent?function(){var c=b(a);d.handleEvent.call(d,c)}:function(){var c=b(a);d.call(a,c)},a.attachEvent("on"+c,a[c+d])});var e=function(){};c.removeEventListener?e=function(a,b,c){a.removeEventListener(b,c,!1)}:c.detachEvent&&(e=function(a,b,c){a.detachEvent("on"+b,a[b+c]);try{delete a[b+c]}catch(d){a[b+c]=void 0}});var f={bind:d,unbind:e};"function"==typeof define&&define.amd?define("eventie/eventie",f):"object"==typeof exports?module.exports=f:a.eventie=f}(this),function(a){function b(a){"function"==typeof a&&(b.isReady?a():f.push(a))}function c(a){var c="readystatechange"===a.type&&"complete"!==e.readyState;if(!b.isReady&&!c){b.isReady=!0;for(var d=0,g=f.length;g>d;d++){var h=f[d];h()}}}function d(d){return d.bind(e,"DOMContentLoaded",c),d.bind(e,"readystatechange",c),d.bind(a,"load",c),b}var e=a.document,f=[];b.isReady=!1,"function"==typeof define&&define.amd?(b.isReady="function"==typeof requirejs,define("doc-ready/doc-ready",["eventie/eventie"],d)):a.docReady=d(a.eventie)}(this),function(){function a(){}function b(a,b){for(var c=a.length;c--;)if(a[c].listener===b)return c;return-1}function c(a){return function(){return this[a].apply(this,arguments)}}var d=a.prototype,e=this,f=e.EventEmitter;d.getListeners=function(a){var b,c,d=this._getEvents();if(a instanceof RegExp){b={};for(c in d)d.hasOwnProperty(c)&&a.test(c)&&(b[c]=d[c])}else b=d[a]||(d[a]=[]);return b},d.flattenListeners=function(a){var b,c=[];for(b=0;be;e++)if(b=c[e]+a,"string"==typeof d[b])return b}}var c="Webkit Moz ms Ms O".split(" "),d=document.documentElement.style;"function"==typeof define&&define.amd?define("get-style-property/get-style-property",[],function(){return b}):"object"==typeof exports?module.exports=b:a.getStyleProperty=b}(window),function(a){function b(a){var b=parseFloat(a),c=-1===a.indexOf("%")&&!isNaN(b);return c&&b}function c(){for(var a={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},b=0,c=g.length;c>b;b++){var d=g[b];a[d]=0}return a}function d(a){function d(a){if("string"==typeof a&&(a=document.querySelector(a)),a&&"object"==typeof a&&a.nodeType){var d=f(a);if("none"===d.display)return c();var e={};e.width=a.offsetWidth,e.height=a.offsetHeight;for(var k=e.isBorderBox=!(!j||!d[j]||"border-box"!==d[j]),l=0,m=g.length;m>l;l++){var n=g[l],o=d[n];o=h(a,o);var p=parseFloat(o);e[n]=isNaN(p)?0:p}var q=e.paddingLeft+e.paddingRight,r=e.paddingTop+e.paddingBottom,s=e.marginLeft+e.marginRight,t=e.marginTop+e.marginBottom,u=e.borderLeftWidth+e.borderRightWidth,v=e.borderTopWidth+e.borderBottomWidth,w=k&&i,x=b(d.width);x!==!1&&(e.width=x+(w?0:q+u));var y=b(d.height);return y!==!1&&(e.height=y+(w?0:r+v)),e.innerWidth=e.width-(q+u),e.innerHeight=e.height-(r+v),e.outerWidth=e.width+s,e.outerHeight=e.height+t,e}}function h(a,b){if(e||-1===b.indexOf("%"))return b;var c=a.style,d=c.left,f=a.runtimeStyle,g=f&&f.left;return g&&(f.left=a.currentStyle.left),c.left=b,b=c.pixelLeft,c.left=d,g&&(f.left=g),b}var i,j=a("boxSizing");return function(){if(j){var a=document.createElement("div");a.style.width="200px",a.style.padding="1px 2px 3px 4px",a.style.borderStyle="solid",a.style.borderWidth="1px 2px 3px 4px",a.style[j]="border-box";var c=document.body||document.documentElement;c.appendChild(a);var d=f(a);i=200===b(d.width),c.removeChild(a)}}(),d}var e=a.getComputedStyle,f=e?function(a){return e(a,null)}:function(a){return a.currentStyle},g=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];"function"==typeof define&&define.amd?define("get-size/get-size",["get-style-property/get-style-property"],d):"object"==typeof exports?module.exports=d(require("get-style-property")):a.getSize=d(a.getStyleProperty)}(window),function(a,b){function c(a,b){return a[h](b)}function d(a){if(!a.parentNode){var b=document.createDocumentFragment();b.appendChild(a)}}function e(a,b){d(a);for(var c=a.parentNode.querySelectorAll(b),e=0,f=c.length;f>e;e++)if(c[e]===a)return!0;return!1}function f(a,b){return d(a),c(a,b)}var g,h=function(){if(b.matchesSelector)return"matchesSelector";for(var a=["webkit","moz","ms","o"],c=0,d=a.length;d>c;c++){var e=a[c],f=e+"MatchesSelector";if(b[f])return f}}();if(h){var i=document.createElement("div"),j=c(i,"div");g=j?c:f}else g=e;"function"==typeof define&&define.amd?define("matches-selector/matches-selector",[],function(){return g}):window.matchesSelector=g}(this,Element.prototype),function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}function c(a){for(var b in a)return!1;return b=null,!0}function d(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function e(a,e,f){function h(a,b){a&&(this.element=a,this.layout=b,this.position={x:0,y:0},this._create())}var i=f("transition"),j=f("transform"),k=i&&j,l=!!f("perspective"),m={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"}[i],n=["transform","transition","transitionDuration","transitionProperty"],o=function(){for(var a={},b=0,c=n.length;c>b;b++){var d=n[b],e=f(d);e&&e!==d&&(a[d]=e)}return a}();b(h.prototype,a.prototype),h.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},h.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},h.prototype.getSize=function(){this.size=e(this.element)},h.prototype.css=function(a){var b=this.element.style;for(var c in a){var d=o[c]||c;b[d]=a[c]}},h.prototype.getPosition=function(){var a=g(this.element),b=this.layout.options,c=b.isOriginLeft,d=b.isOriginTop,e=parseInt(a[c?"left":"right"],10),f=parseInt(a[d?"top":"bottom"],10);e=isNaN(e)?0:e,f=isNaN(f)?0:f;var h=this.layout.size;e-=c?h.paddingLeft:h.paddingRight,f-=d?h.paddingTop:h.paddingBottom,this.position.x=e,this.position.y=f},h.prototype.layoutPosition=function(){var a=this.layout.size,b=this.layout.options,c={};b.isOriginLeft?(c.left=this.position.x+a.paddingLeft+"px",c.right=""):(c.right=this.position.x+a.paddingRight+"px",c.left=""),b.isOriginTop?(c.top=this.position.y+a.paddingTop+"px",c.bottom=""):(c.bottom=this.position.y+a.paddingBottom+"px",c.top=""),this.css(c),this.emitEvent("layout",[this])};var p=l?function(a,b){return"translate3d("+a+"px, "+b+"px, 0)"}:function(a,b){return"translate("+a+"px, "+b+"px)"};h.prototype._transitionTo=function(a,b){this.getPosition();var c=this.position.x,d=this.position.y,e=parseInt(a,10),f=parseInt(b,10),g=e===this.position.x&&f===this.position.y;if(this.setPosition(a,b),g&&!this.isTransitioning)return void this.layoutPosition();var h=a-c,i=b-d,j={},k=this.layout.options;h=k.isOriginLeft?h:-h,i=k.isOriginTop?i:-i,j.transform=p(h,i),this.transition({to:j,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},h.prototype.goTo=function(a,b){this.setPosition(a,b),this.layoutPosition()},h.prototype.moveTo=k?h.prototype._transitionTo:h.prototype.goTo,h.prototype.setPosition=function(a,b){this.position.x=parseInt(a,10),this.position.y=parseInt(b,10)},h.prototype._nonTransition=function(a){this.css(a.to),a.isCleaning&&this._removeStyles(a.to);for(var b in a.onTransitionEnd)a.onTransitionEnd[b].call(this)},h.prototype._transition=function(a){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(a);var b=this._transn;for(var c in a.onTransitionEnd)b.onEnd[c]=a.onTransitionEnd[c];for(c in a.to)b.ingProperties[c]=!0,a.isCleaning&&(b.clean[c]=!0);if(a.from){this.css(a.from);var d=this.element.offsetHeight;d=null}this.enableTransition(a.to),this.css(a.to),this.isTransitioning=!0};var q=j&&d(j)+",opacity";h.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:q,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(m,this,!1))},h.prototype.transition=h.prototype[i?"_transition":"_nonTransition"],h.prototype.onwebkitTransitionEnd=function(a){this.ontransitionend(a)},h.prototype.onotransitionend=function(a){this.ontransitionend(a)};var r={"-webkit-transform":"transform","-moz-transform":"transform","-o-transform":"transform"};h.prototype.ontransitionend=function(a){if(a.target===this.element){var b=this._transn,d=r[a.propertyName]||a.propertyName;if(delete b.ingProperties[d],c(b.ingProperties)&&this.disableTransition(),d in b.clean&&(this.element.style[a.propertyName]="",delete b.clean[d]),d in b.onEnd){var e=b.onEnd[d];e.call(this),delete b.onEnd[d]}this.emitEvent("transitionEnd",[this])}},h.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(m,this,!1),this.isTransitioning=!1},h.prototype._removeStyles=function(a){var b={};for(var c in a)b[c]="";this.css(b)};var s={transitionProperty:"",transitionDuration:""};return h.prototype.removeTransitionStyles=function(){this.css(s)},h.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.emitEvent("remove",[this])},h.prototype.remove=function(){if(!i||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var a=this;this.on("transitionEnd",function(){return a.removeElem(),!0}),this.hide()},h.prototype.reveal=function(){delete this.isHidden,this.css({display:""});var a=this.layout.options;this.transition({from:a.hiddenStyle,to:a.visibleStyle,isCleaning:!0})},h.prototype.hide=function(){this.isHidden=!0,this.css({display:""});var a=this.layout.options;this.transition({from:a.visibleStyle,to:a.hiddenStyle,isCleaning:!0,onTransitionEnd:{opacity:function(){this.isHidden&&this.css({display:"none"})}}})},h.prototype.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},h}var f=a.getComputedStyle,g=f?function(a){return f(a,null)}:function(a){return a.currentStyle};"function"==typeof define&&define.amd?define("outlayer/item",["eventEmitter/EventEmitter","get-size/get-size","get-style-property/get-style-property"],e):(a.Outlayer={},a.Outlayer.Item=e(a.EventEmitter,a.getSize,a.getStyleProperty))}(window),function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}function c(a){return"[object Array]"===l.call(a)}function d(a){var b=[];if(c(a))b=a;else if(a&&"number"==typeof a.length)for(var d=0,e=a.length;e>d;d++)b.push(a[d]);else b.push(a);return b}function e(a,b){var c=n(b,a);-1!==c&&b.splice(c,1)}function f(a){return a.replace(/(.)([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()}function g(c,g,l,n,o,p){function q(a,c){if("string"==typeof a&&(a=h.querySelector(a)),!a||!m(a))return void(i&&i.error("Bad "+this.constructor.namespace+" element: "+a));this.element=a,this.options=b({},this.constructor.defaults),this.option(c);var d=++r;this.element.outlayerGUID=d,s[d]=this,this._create(),this.options.isInitLayout&&this.layout()}var r=0,s={};return q.namespace="outlayer",q.Item=p,q.defaults={containerStyle:{position:"relative"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}},b(q.prototype,l.prototype),q.prototype.option=function(a){b(this.options,a)},q.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),b(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},q.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},q.prototype._itemize=function(a){for(var b=this._filterFindItemElements(a),c=this.constructor.Item,d=[],e=0,f=b.length;f>e;e++){var g=b[e],h=new c(g,this);d.push(h)}return d},q.prototype._filterFindItemElements=function(a){a=d(a);for(var b=this.options.itemSelector,c=[],e=0,f=a.length;f>e;e++){var g=a[e];if(m(g))if(b){o(g,b)&&c.push(g);for(var h=g.querySelectorAll(b),i=0,j=h.length;j>i;i++)c.push(h[i])}else c.push(g)}return c},q.prototype.getItemElements=function(){for(var a=[],b=0,c=this.items.length;c>b;b++)a.push(this.items[b].element);return a},q.prototype.layout=function(){this._resetLayout(),this._manageStamps();var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,a),this._isLayoutInited=!0},q.prototype._init=q.prototype.layout,q.prototype._resetLayout=function(){this.getSize()},q.prototype.getSize=function(){this.size=n(this.element)},q.prototype._getMeasurement=function(a,b){var c,d=this.options[a];d?("string"==typeof d?c=this.element.querySelector(d):m(d)&&(c=d),this[a]=c?n(c)[b]:d):this[a]=0},q.prototype.layoutItems=function(a,b){a=this._getItemsForLayout(a),this._layoutItems(a,b),this._postLayout()},q.prototype._getItemsForLayout=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];e.isIgnored||b.push(e)}return b},q.prototype._layoutItems=function(a,b){function c(){d.emitEvent("layoutComplete",[d,a])}var d=this;if(!a||!a.length)return void c();this._itemsOn(a,"layout",c);for(var e=[],f=0,g=a.length;g>f;f++){var h=a[f],i=this._getItemLayoutPosition(h);i.item=h,i.isInstant=b||h.isLayoutInstant,e.push(i)}this._processLayoutQueue(e)},q.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},q.prototype._processLayoutQueue=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];this._positionItem(d.item,d.x,d.y,d.isInstant)}},q.prototype._positionItem=function(a,b,c,d){d?a.goTo(b,c):a.moveTo(b,c)},q.prototype._postLayout=function(){this.resizeContainer()},q.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var a=this._getContainerSize();a&&(this._setContainerMeasure(a.width,!0),this._setContainerMeasure(a.height,!1))}},q.prototype._getContainerSize=k,q.prototype._setContainerMeasure=function(a,b){if(void 0!==a){var c=this.size;c.isBorderBox&&(a+=b?c.paddingLeft+c.paddingRight+c.borderLeftWidth+c.borderRightWidth:c.paddingBottom+c.paddingTop+c.borderTopWidth+c.borderBottomWidth),a=Math.max(a,0),this.element.style[b?"width":"height"]=a+"px"}},q.prototype._itemsOn=function(a,b,c){function d(){return e++,e===f&&c.call(g),!0}for(var e=0,f=a.length,g=this,h=0,i=a.length;i>h;h++){var j=a[h];j.on(b,d)}},q.prototype.ignore=function(a){var b=this.getItem(a);b&&(b.isIgnored=!0)},q.prototype.unignore=function(a){var b=this.getItem(a);b&&delete b.isIgnored},q.prototype.stamp=function(a){if(a=this._find(a)){this.stamps=this.stamps.concat(a);for(var b=0,c=a.length;c>b;b++){var d=a[b];this.ignore(d)}}},q.prototype.unstamp=function(a){if(a=this._find(a))for(var b=0,c=a.length;c>b;b++){var d=a[b];e(d,this.stamps),this.unignore(d)}},q.prototype._find=function(a){return a?("string"==typeof a&&(a=this.element.querySelectorAll(a)),a=d(a)):void 0},q.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var a=0,b=this.stamps.length;b>a;a++){var c=this.stamps[a];this._manageStamp(c)}}},q.prototype._getBoundingRect=function(){var a=this.element.getBoundingClientRect(),b=this.size;this._boundingRect={left:a.left+b.paddingLeft+b.borderLeftWidth,top:a.top+b.paddingTop+b.borderTopWidth,right:a.right-(b.paddingRight+b.borderRightWidth),bottom:a.bottom-(b.paddingBottom+b.borderBottomWidth)}},q.prototype._manageStamp=k,q.prototype._getElementOffset=function(a){var b=a.getBoundingClientRect(),c=this._boundingRect,d=n(a),e={left:b.left-c.left-d.marginLeft,top:b.top-c.top-d.marginTop,right:c.right-b.right-d.marginRight,bottom:c.bottom-b.bottom-d.marginBottom};return e},q.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},q.prototype.bindResize=function(){this.isResizeBound||(c.bind(a,"resize",this),this.isResizeBound=!0)},q.prototype.unbindResize=function(){this.isResizeBound&&c.unbind(a,"resize",this),this.isResizeBound=!1},q.prototype.onresize=function(){function a(){b.resize(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},q.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},q.prototype.needsResizeLayout=function(){var a=n(this.element),b=this.size&&a;return b&&a.innerWidth!==this.size.innerWidth},q.prototype.addItems=function(a){var b=this._itemize(a);return b.length&&(this.items=this.items.concat(b)),b},q.prototype.appended=function(a){var b=this.addItems(a);b.length&&(this.layoutItems(b,!0),this.reveal(b))},q.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){var c=this.items.slice(0);this.items=b.concat(c),this._resetLayout(),this._manageStamps(),this.layoutItems(b,!0),this.reveal(b),this.layoutItems(c)}},q.prototype.reveal=function(a){var b=a&&a.length;if(b)for(var c=0;b>c;c++){var d=a[c];d.reveal()}},q.prototype.hide=function(a){var b=a&&a.length;if(b)for(var c=0;b>c;c++){var d=a[c];d.hide()}},q.prototype.getItem=function(a){for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];if(d.element===a)return d}},q.prototype.getItems=function(a){if(a&&a.length){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c],f=this.getItem(e);f&&b.push(f)}return b}},q.prototype.remove=function(a){a=d(a);var b=this.getItems(a);if(b&&b.length){this._itemsOn(b,"remove",function(){this.emitEvent("removeComplete",[this,b])});for(var c=0,f=b.length;f>c;c++){var g=b[c];g.remove(),e(g,this.items)}}},q.prototype.destroy=function(){var a=this.element.style;a.height="",a.position="",a.width="";for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];d.destroy()}this.unbindResize(),delete this.element.outlayerGUID,j&&j.removeData(this.element,this.constructor.namespace)},q.data=function(a){var b=a&&a.outlayerGUID;return b&&s[b]},q.create=function(a,c){function d(){q.apply(this,arguments)}return Object.create?d.prototype=Object.create(q.prototype):b(d.prototype,q.prototype),d.prototype.constructor=d,d.defaults=b({},q.defaults),b(d.defaults,c),d.prototype.settings={},d.namespace=a,d.data=q.data,d.Item=function(){p.apply(this,arguments)},d.Item.prototype=new p,g(function(){for(var b=f(a),c=h.querySelectorAll(".js-"+b),e="data-"+b+"-options",g=0,k=c.length;k>g;g++){var l,m=c[g],n=m.getAttribute(e);try{l=n&&JSON.parse(n)}catch(o){i&&i.error("Error parsing "+e+" on "+m.nodeName.toLowerCase()+(m.id?"#"+m.id:"")+": "+o);continue}var p=new d(m,l);j&&j.data(m,a,p)}}),j&&j.bridget&&j.bridget(a,d),d},q.Item=p,q}var h=a.document,i=a.console,j=a.jQuery,k=function(){},l=Object.prototype.toString,m="object"==typeof HTMLElement?function(a){return a instanceof HTMLElement}:function(a){return a&&"object"==typeof a&&1===a.nodeType&&"string"==typeof a.nodeName},n=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1};"function"==typeof define&&define.amd?define("outlayer/outlayer",["eventie/eventie","doc-ready/doc-ready","eventEmitter/EventEmitter","get-size/get-size","matches-selector/matches-selector","./item"],g):a.Outlayer=g(a.eventie,a.docReady,a.EventEmitter,a.getSize,a.matchesSelector,a.Outlayer.Item)}(window),function(a){function b(a,b){var d=a.create("masonry");return d.prototype._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns();var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0);this.maxY=0},d.prototype.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var a=this.items[0],c=a&&a.element;this.columnWidth=c&&b(c).outerWidth||this.containerWidth}this.columnWidth+=this.gutter,this.cols=Math.floor((this.containerWidth+this.gutter)/this.columnWidth),this.cols=Math.max(this.cols,1)},d.prototype.getContainerWidth=function(){var a=this.options.isFitWidth?this.element.parentNode:this.element,c=b(a);this.containerWidth=c&&c.innerWidth},d.prototype._getItemLayoutPosition=function(a){a.getSize();var b=a.size.outerWidth%this.columnWidth,d=b&&1>b?"round":"ceil",e=Math[d](a.size.outerWidth/this.columnWidth);e=Math.min(e,this.cols);for(var f=this._getColGroup(e),g=Math.min.apply(Math,f),h=c(f,g),i={x:this.columnWidth*h,y:g},j=g+a.size.outerHeight,k=this.cols+1-f.length,l=0;k>l;l++)this.colYs[h+l]=j;return i},d.prototype._getColGroup=function(a){if(2>a)return this.colYs;for(var b=[],c=this.cols+1-a,d=0;c>d;d++){var e=this.colYs.slice(d,d+a);b[d]=Math.max.apply(Math,e)}return b},d.prototype._manageStamp=function(a){var c=b(a),d=this._getElementOffset(a),e=this.options.isOriginLeft?d.left:d.right,f=e+c.outerWidth,g=Math.floor(e/this.columnWidth);g=Math.max(0,g);var h=Math.floor(f/this.columnWidth);h-=f%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var i=(this.options.isOriginTop?d.top:d.bottom)+c.outerHeight,j=g;h>=j;j++)this.colYs[j]=Math.max(i,this.colYs[j])},d.prototype._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var a={height:this.maxY};return this.options.isFitWidth&&(a.width=this._getContainerFitWidth()),a},d.prototype._getContainerFitWidth=function(){for(var a=0,b=this.cols;--b&&0===this.colYs[b];)a++;return(this.cols-a)*this.columnWidth-this.gutter},d.prototype.needsResizeLayout=function(){var a=this.containerWidth;return this.getContainerWidth(),a!==this.containerWidth},d}var c=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++){var e=a[c];if(e===b)return c}return-1};"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size"],b):a.Masonry=b(a.Outlayer,a.getSize)}(window);
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/js/jquery.qtip.js b/wp-content/themes/headway/library/admin/js/jquery.qtip.js
new file mode 100644
index 0000000..ccc6128
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/js/jquery.qtip.js
@@ -0,0 +1,5 @@
+/* qTip2 v2.2.0 tips viewport | qtip2.com | Licensed MIT, GPL | Mon Dec 16 2013 11:39:27 */
+
+!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=E,this.elements={target:a},this._id=R+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:D,attr:e,onTooltip:D,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=D}function f(a){return a===E||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?D:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?b=a.content={text:c=g(b)?D:b}:c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==D,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context:b})).then(e.success,E,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(f(b.title)||(b.button=b.title.button,b.title=b.title.text),g(b.title||D)&&(b.title=D))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===C?{ready:C}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(Q,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d0?setTimeout(d.proxy(a,this),b):(a.call(this),void 0)}function n(a){return this.tooltip.hasClass(_)?D:(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=m.call(this,function(){this.toggle(C,a)},this.options.show.delay),void 0)}function o(a){if(this.tooltip.hasClass(_))return D;var b=d(a.relatedTarget),c=b.closest(V)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=m.call(this,function(){this.toggle(D,a)},this.options.hide.delay,this)}function p(a){return this.tooltip.hasClass(_)||!this.options.hide.inactive?D:(clearTimeout(this.timers.inactive),this.timers.inactive=m.call(this,function(){this.hide(a)},this.options.hide.inactive),void 0)}function q(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function r(a,c,e){d(b.body).delegate(a,(c.split?c:c.join(gb+" "))+gb,function(){var a=x.api[d.attr(this,T)];a&&!a.disabled&&e.apply(a,arguments)})}function s(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):E,p="html5"===f.metadata.type&&o?o[f.metadata.name]:E,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(C,{},x.defaults,f,"object"==typeof q?h(q):E,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===D||!j)return D;k.content.text=j}if(i.container.length||(i.container=m),i.target===D&&(i.target=n),k.show.target===D&&(k.show.target=n),k.show.solo===C&&(k.show.solo=i.container.closest("body")),k.hide.target===D&&(k.hide.target=n),k.position.viewport===C&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new z(i.at,C),i.my=new z(i.my),a.data(R))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===D)return D;return a.attr(S,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(bb,l).attr("title",""),g=new e(a,k,c,!!j),a.data(R,g),a.one("remove.qtip-"+c+" removeqtip.qtip-"+c,function(){var a;(a=d(this).data(R))&&a.destroy(!0)}),g}function t(a){return a.charAt(0).toUpperCase()+a.slice(1)}function u(a,b){var d,e,f=b.charAt(0).toUpperCase()+b.slice(1),g=(b+" "+rb.join(f+" ")+f).split(" "),h=0;if(qb[b])return a.css(qb[b]);for(;d=g[h++];)if((e=a.css(d))!==c)return qb[b]=d,e}function v(a,b){return Math.ceil(parseFloat(u(a,b)))}function w(a,b){this._ns="tip",this.options=b,this.offset=b.offset,this.size=[b.width,b.height],this.init(this.qtip=a)}var x,y,z,A,B,C=!0,D=!1,E=null,F="x",G="y",H="width",I="height",J="top",K="left",L="bottom",M="right",N="center",O="flipinvert",P="shift",Q={},R="qtip",S="data-hasqtip",T="data-qtip-id",U=["ui-widget","ui-tooltip"],V="."+R,W="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),X=R+"-fixed",Y=R+"-default",Z=R+"-focus",$=R+"-hover",_=R+"-disabled",ab="_replacedByqTip",bb="oldtitle",cb={ie:function(){for(var a=3,c=b.createElement("div");(c.innerHTML="")&&c.getElementsByTagName("i")[0];);return a>4?a:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||D};y=e.prototype,y._when=function(a){return d.when.apply(d,a)},y.render=function(a){if(this.rendered||this.destroyed)return this;var b,c=this,e=this.options,f=this.cache,g=this.elements,h=e.content.text,i=e.content.title,j=e.content.button,k=e.position,l=("."+this._id+" ",[]);return d.attr(this.target[0],"aria-describedby",this._id),this.tooltip=g.tooltip=b=d("",{id:this._id,"class":[R,Y,e.style.classes,R+"-pos-"+e.position.my.abbrev()].join(" "),width:e.style.width||"",height:e.style.height||"",tracking:"mouse"===k.target&&k.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":D,"aria-describedby":this._id+"-content","aria-hidden":C}).toggleClass(_,this.disabled).attr(T,this.id).data(R,this).appendTo(k.container).append(g.content=d("",{"class":R+"-content",id:this._id+"-content","aria-atomic":C})),this.rendered=-1,this.positioning=C,i&&(this._createTitle(),d.isFunction(i)||l.push(this._updateTitle(i,D))),j&&this._createButton(),d.isFunction(h)||l.push(this._updateContent(h,D)),this.rendered=C,this._setWidget(),d.each(Q,function(a){var b;"render"===this.initialize&&(b=this(c))&&(c.plugins[a]=b)}),this._unassignEvents(),this._assignEvents(),this._when(l).then(function(){c._trigger("render"),c.positioning=D,c.hiddenDuringWait||!e.show.ready&&!a||c.toggle(C,f.event,D),c.hiddenDuringWait=D}),x.api[this.id]=this,this},y.destroy=function(a){function b(){if(!this.destroyed){this.destroyed=C;var a=this.target,b=a.attr(bb);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),d.each(this.plugins,function(){this.destroy&&this.destroy()}),clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this._unassignEvents(),a.removeData(R).removeAttr(T).removeAttr(S).removeAttr("aria-describedby"),this.options.suppress&&b&&a.attr("title",b).removeAttr(bb),this._unbind(a),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=E,delete x.api[this.id]}}return this.destroyed?this.target:(a===C&&"hide"!==this.triggering||!this.rendered?b.call(this):(this.tooltip.one("tooltiphidden",d.proxy(b,this)),!this.triggering&&this.hide()),this.target)},A=y.checks={builtin:{"^id$":function(a,b,c,e){var f=c===C?x.nextid:c,g=R+"-"+f;f!==D&&f.length>0&&!d("#"+g).length?(this._id=g,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):a[b]=e},"^prerender":function(a,b,c){c&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(a,b,c){this._updateContent(c)},"^content.attr$":function(a,b,c,d){this.options.content.text===this.target.attr(d)&&this._updateContent(this.target.attr(c))},"^content.title$":function(a,b,c){return c?(c&&!this.elements.title&&this._createTitle(),this._updateTitle(c),void 0):this._removeTitle()},"^content.button$":function(a,b,c){this._updateButton(c)},"^content.title.(text|button)$":function(a,b,c){this.set("content."+b,c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(a[b]=new z(c,"at"===b))},"^position.container$":function(a,b,c){this.rendered&&this.tooltip.appendTo(c)},"^show.ready$":function(a,b,c){c&&(!this.rendered&&this.render(C)||this.toggle(C))},"^style.classes$":function(a,b,c,d){this.rendered&&this.tooltip.removeClass(d).addClass(c)},"^style.(width|height)":function(a,b,c){this.rendered&&this.tooltip.css(b,c)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(a,b,c){this.rendered&&this.tooltip.toggleClass(Y,!!c)},"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){this.rendered&&this.tooltip[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var a=this.options.position;this.tooltip.attr("tracking","mouse"===a.target&&a.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},y.get=function(a){if(this.destroyed)return this;var b=i(this.options,a.toLowerCase()),c=b[0][b[1]];return c.precedance?c.string():c};var db=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,eb=/^prerender|show\.ready/i;y.set=function(a,b){if(this.destroyed)return this;{var c,e=this.rendered,f=D,g=this.options;this.checks}return"string"==typeof a?(c=a,a={},a[c]=b):a=d.extend({},a),d.each(a,function(b,c){if(e&&eb.test(b))return delete a[b],void 0;var h,j=i(g,b.toLowerCase());h=j[0][j[1]],j[0][j[1]]=c&&c.nodeType?d(c):c,f=db.test(b)||f,a[b]=[j[0],j[1],c,h]}),h(g),this.positioning=C,d.each(a,d.proxy(j,this)),this.positioning=D,this.rendered&&this.tooltip[0].offsetWidth>0&&f&&this.reposition("mouse"===g.position.target?E:this.cache.event),this},y._update=function(a,b){var c=this,e=this.cache;return this.rendered&&a?(d.isFunction(a)&&(a=a.call(this.elements.target,e.event,this)||""),d.isFunction(a.then)?(e.waiting=C,a.then(function(a){return e.waiting=D,c._update(a,b)},E,function(a){return c._update(a,b)})):a===D||!a&&""!==a?D:(a.jquery&&a.length>0?b.empty().append(a.css({display:"block",visibility:"visible"})):b.html(a),this._waitForContent(b).then(function(a){a.images&&a.images.length&&c.rendered&&c.tooltip[0].offsetWidth>0&&c.reposition(e.event,!a.length)}))):D},y._waitForContent=function(a){var b=this.cache;return b.waiting=C,(d.fn.imagesLoaded?a.imagesLoaded():d.Deferred().resolve([])).done(function(){b.waiting=D}).promise()},y._updateContent=function(a,b){this._update(a,this.elements.content,b)},y._updateTitle=function(a,b){this._update(a,this.elements.title,b)===D&&this._removeTitle(D)},y._createTitle=function(){var a=this.elements,b=this._id+"-title";a.titlebar&&this._removeTitle(),a.titlebar=d("",{"class":R+"-titlebar "+(this.options.style.widget?k("header"):"")}).append(a.title=d("",{id:b,"class":R+"-title","aria-atomic":C})).insertBefore(a.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus","down"===a.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover","mouseover"===a.type)}),this.options.content.button&&this._createButton()},y._removeTitle=function(a){var b=this.elements;b.title&&(b.titlebar.remove(),b.titlebar=b.title=b.button=E,a!==D&&this.reposition())},y.reposition=function(c,e){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=C;var f,g,h=this.cache,i=this.tooltip,j=this.options.position,k=j.target,l=j.my,m=j.at,n=j.viewport,o=j.container,p=j.adjust,q=p.method.split(" "),r=i.outerWidth(D),s=i.outerHeight(D),t=0,u=0,v=i.css("position"),w={left:0,top:0},x=i[0].offsetWidth>0,y=c&&"scroll"===c.type,z=d(a),A=o[0].ownerDocument,B=this.mouse;if(d.isArray(k)&&2===k.length)m={x:K,y:J},w={left:k[0],top:k[1]};else if("mouse"===k)m={x:K,y:J},!B||!B.pageX||!p.mouse&&c&&c.pageX?c&&c.pageX||((!p.mouse||this.options.show.distance)&&h.origin&&h.origin.pageX?c=h.origin:(!c||c&&("resize"===c.type||"scroll"===c.type))&&(c=h.event)):c=B,"static"!==v&&(w=o.offset()),A.body.offsetWidth!==(a.innerWidth||A.documentElement.clientWidth)&&(g=d(b.body).offset()),w={left:c.pageX-w.left+(g&&g.left||0),top:c.pageY-w.top+(g&&g.top||0)},p.mouse&&y&&B&&(w.left-=(B.scrollX||0)-z.scrollLeft(),w.top-=(B.scrollY||0)-z.scrollTop());else{if("event"===k?c&&c.target&&"scroll"!==c.type&&"resize"!==c.type?h.target=d(c.target):c.target||(h.target=this.elements.target):"event"!==k&&(h.target=d(k.jquery?k:this.elements.target)),k=h.target,k=d(k).eq(0),0===k.length)return this;k[0]===b||k[0]===a?(t=cb.iOS?a.innerWidth:k.width(),u=cb.iOS?a.innerHeight:k.height(),k[0]===a&&(w={top:(n||k).scrollTop(),left:(n||k).scrollLeft()})):Q.imagemap&&k.is("area")?f=Q.imagemap(this,k,m,Q.viewport?q:D):Q.svg&&k&&k[0].ownerSVGElement?f=Q.svg(this,k,m,Q.viewport?q:D):(t=k.outerWidth(D),u=k.outerHeight(D),w=k.offset()),f&&(t=f.width,u=f.height,g=f.offset,w=f.position),w=this.reposition.offset(k,w,o),(cb.iOS>3.1&&cb.iOS<4.1||cb.iOS>=4.3&&cb.iOS<4.33||!cb.iOS&&"fixed"===v)&&(w.left-=z.scrollLeft(),w.top-=z.scrollTop()),(!f||f&&f.adjustable!==D)&&(w.left+=m.x===M?t:m.x===N?t/2:0,w.top+=m.y===L?u:m.y===N?u/2:0)}return w.left+=p.x+(l.x===M?-r:l.x===N?-r/2:0),w.top+=p.y+(l.y===L?-s:l.y===N?-s/2:0),Q.viewport?(w.adjusted=Q.viewport(this,w,j,t,u,r,s),g&&w.adjusted.left&&(w.left+=g.left),g&&w.adjusted.top&&(w.top+=g.top)):w.adjusted={left:0,top:0},this._trigger("move",[w,n.elem||n],c)?(delete w.adjusted,e===D||!x||isNaN(w.left)||isNaN(w.top)||"mouse"===k||!d.isFunction(j.effect)?i.css(w):d.isFunction(j.effect)&&(j.effect.call(i,this,d.extend({},w)),i.queue(function(a){d(this).css({opacity:"",height:""}),cb.ie&&this.style.removeAttribute("filter"),a()})),this.positioning=D,this):this},y.reposition.offset=function(a,c,e){function f(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}if(!e[0])return c;var g,h,i,j,k=d(a[0].ownerDocument),l=!!cb.ie&&"CSS1Compat"!==b.compatMode,m=e[0];do"static"!==(h=d.css(m,"position"))&&("fixed"===h?(i=m.getBoundingClientRect(),f(k,-1)):(i=d(m).position(),i.left+=parseFloat(d.css(m,"borderLeftWidth"))||0,i.top+=parseFloat(d.css(m,"borderTopWidth"))||0),c.left-=i.left+(parseFloat(d.css(m,"marginLeft"))||0),c.top-=i.top+(parseFloat(d.css(m,"marginTop"))||0),g||"hidden"===(j=d.css(m,"overflow"))||"visible"===j||(g=d(m)));while(m=m.offsetParent);return g&&(g[0]!==k[0]||l)&&f(g,1),c};var fb=(z=y.reposition.Corner=function(a,b){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,N).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!b;var c=a.charAt(0);this.precedance="t"===c||"b"===c?G:F}).prototype;fb.invert=function(a,b){this[a]=this[a]===K?M:this[a]===M?K:b||this[a]},fb.string=function(){var a=this.x,b=this.y;return a===b?a:this.precedance===G||this.forceY&&"center"!==b?b+" "+a:a+" "+b},fb.abbrev=function(){var a=this.string().split(" ");return a[0].charAt(0)+(a[1]&&a[1].charAt(0)||"")},fb.clone=function(){return new z(this.string(),this.forceY)},y.toggle=function(a,c){var e=this.cache,f=this.options,g=this.tooltip;if(c){if(/over|enter/.test(c.type)&&/out|leave/.test(e.event.type)&&f.show.target.add(c.target).length===f.show.target.length&&g.has(c.relatedTarget).length)return this;e.event=l(c)}if(this.waiting&&!a&&(this.hiddenDuringWait=C),!this.rendered)return a?this.render(1):this;if(this.destroyed||this.disabled)return this;var h,i,j,k=a?"show":"hide",m=this.options[k],n=(this.options[a?"hide":"show"],this.options.position),o=this.options.content,p=this.tooltip.css("width"),q=this.tooltip.is(":visible"),r=a||1===m.target.length,s=!c||m.target.length<2||e.target[0]===c.target;return(typeof a).search("boolean|number")&&(a=!q),h=!g.is(":animated")&&q===a&&s,i=h?E:!!this._trigger(k,[90]),this.destroyed?this:(i!==D&&a&&this.focus(c),!i||h?this:(d.attr(g[0],"aria-hidden",!a),a?(e.origin=l(this.mouse),d.isFunction(o.text)&&this._updateContent(o.text,D),d.isFunction(o.title)&&this._updateTitle(o.title,D),!B&&"mouse"===n.target&&n.adjust.mouse&&(d(b).bind("mousemove."+R,this._storeMouse),B=C),p||g.css("width",g.outerWidth(D)),this.reposition(c,arguments[2]),p||g.css("width",""),m.solo&&("string"==typeof m.solo?d(m.solo):d(V,m.solo)).not(g).not(m.target).qtip("hide",d.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete e.origin,B&&!d(V+'[tracking="true"]:visible',m.solo).not(g).length&&(d(b).unbind("mousemove."+R),B=D),this.blur(c)),j=d.proxy(function(){a?(cb.ie&&g[0].style.removeAttribute("filter"),g.css("overflow",""),"string"==typeof m.autofocus&&d(this.options.show.autofocus,g).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):g.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(a?"visible":"hidden")},this),m.effect===D||r===D?(g[k](),j()):d.isFunction(m.effect)?(g.stop(1,1),m.effect.call(g,this),g.queue("fx",function(a){j(),a()})):g.fadeTo(90,a?1:0,j),a&&m.target.trigger("qtip-"+this.id+"-inactive"),this))},y.show=function(a){return this.toggle(C,a)},y.hide=function(a){return this.toggle(D,a)},y.focus=function(a){if(!this.rendered||this.destroyed)return this;var b=d(V),c=this.tooltip,e=parseInt(c[0].style.zIndex,10),f=x.zindex+b.length;return c.hasClass(Z)||this._trigger("focus",[f],a)&&(e!==f&&(b.each(function(){this.style.zIndex>e&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+Z).qtip("blur",a)),c.addClass(Z)[0].style.zIndex=f),this},y.blur=function(a){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass(Z),this._trigger("blur",[this.tooltip.css("zIndex")],a),this)},y.disable=function(a){return this.destroyed?this:("toggle"===a?a=!(this.rendered?this.tooltip.hasClass(_):this.disabled):"boolean"!=typeof a&&(a=C),this.rendered&&this.tooltip.toggleClass(_,a).attr("aria-disabled",a),this.disabled=!!a,this)},y.enable=function(){return this.disable(D)},y._createButton=function(){var a=this,b=this.elements,c=b.tooltip,e=this.options.content.button,f="string"==typeof e,g=f?e:"Close tooltip";b.button&&b.button.remove(),b.button=e.jquery?e:d("",{"class":"qtip-close "+(this.options.style.widget?"":R+"-icon"),title:g,"aria-label":g}).prepend(d("",{"class":"ui-icon ui-icon-close",html:"×"})),b.button.appendTo(b.titlebar||c).attr("role","button").click(function(b){return c.hasClass(_)||a.hide(b),D})},y._updateButton=function(a){if(!this.rendered)return D;var b=this.elements.button;a?this._createButton():b.remove()},y._setWidget=function(){var a=this.options.style.widget,b=this.elements,c=b.tooltip,d=c.hasClass(_);c.removeClass(_),_=a?"ui-state-disabled":"qtip-disabled",c.toggleClass(_,d),c.toggleClass("ui-helper-reset "+k(),a).toggleClass(Y,this.options.style.def&&!a),b.content&&b.content.toggleClass(k("content"),a),b.titlebar&&b.titlebar.toggleClass(k("header"),a),b.button&&b.button.toggleClass(R+"-icon",!a)},y._storeMouse=function(a){(this.mouse=l(a)).type="mousemove"},y._bind=function(a,b,c,e,f){var g="."+this._id+(e?"-"+e:"");b.length&&d(a).bind((b.split?b:b.join(g+" "))+g,d.proxy(c,f||this))},y._unbind=function(a,b){d(a).unbind("."+this._id+(b?"-"+b:""))};var gb="."+R;d(function(){r(V,["mouseenter","mouseleave"],function(a){var b="mouseenter"===a.type,c=d(a.currentTarget),e=d(a.relatedTarget||a.target),f=this.options;b?(this.focus(a),c.hasClass(X)&&!c.hasClass(_)&&clearTimeout(this.timers.hide)):"mouse"===f.position.target&&f.hide.event&&f.show.target&&!e.closest(f.show.target[0]).length&&this.hide(a),c.toggleClass($,b)}),r("["+T+"]",W,p)}),y._trigger=function(a,b,c){var e=d.Event("tooltip"+a);return e.originalEvent=c&&d.extend({},c)||this.cache.event||E,this.triggering=a,this.tooltip.trigger(e,[this].concat(b||[])),this.triggering=D,!e.isDefaultPrevented()},y._bindEvents=function(a,b,c,e,f,g){if(e.add(c).length===e.length){var h=[];b=d.map(b,function(b){var c=d.inArray(b,a);return c>-1?(h.push(a.splice(c,1)[0]),void 0):b}),h.length&&this._bind(c,h,function(a){var b=this.rendered?this.tooltip[0].offsetWidth>0:!1;(b?g:f).call(this,a)})}this._bind(c,a,f),this._bind(e,b,g)},y._assignInitialEvents=function(a){function b(a){return this.disabled||this.destroyed?D:(this.cache.event=l(a),this.cache.target=a?d(a.target):[c],clearTimeout(this.timers.show),this.timers.show=m.call(this,function(){this.render("object"==typeof a||e.show.ready)},e.show.delay),void 0)}var e=this.options,f=e.show.target,g=e.hide.target,h=e.show.event?d.trim(""+e.show.event).split(" "):[],i=e.hide.event?d.trim(""+e.hide.event).split(" "):[];/mouse(over|enter)/i.test(e.show.event)&&!/mouse(out|leave)/i.test(e.hide.event)&&i.push("mouseleave"),this._bind(f,"mousemove",function(a){this._storeMouse(a),this.cache.onTarget=C}),this._bindEvents(h,i,f,g,b,function(){clearTimeout(this.timers.show)}),(e.show.ready||e.prerender)&&b.call(this,a)},y._assignEvents=function(){var c=this,e=this.options,f=e.position,g=this.tooltip,h=e.show.target,i=e.hide.target,j=f.container,k=f.viewport,l=d(b),m=(d(b.body),d(a)),r=e.show.event?d.trim(""+e.show.event).split(" "):[],s=e.hide.event?d.trim(""+e.hide.event).split(" "):[];d.each(e.events,function(a,b){c._bind(g,"toggle"===a?["tooltipshow","tooltiphide"]:["tooltip"+a],b,null,g)}),/mouse(out|leave)/i.test(e.hide.event)&&"window"===e.hide.leave&&this._bind(l,["mouseout","blur"],function(a){/select|option/.test(a.target.nodeName)||a.relatedTarget||this.hide(a)}),e.hide.fixed?i=i.add(g.addClass(X)):/mouse(over|enter)/i.test(e.show.event)&&this._bind(i,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+e.hide.event).indexOf("unfocus")>-1&&this._bind(j.closest("html"),["mousedown","touchstart"],function(a){var b=d(a.target),c=this.rendered&&!this.tooltip.hasClass(_)&&this.tooltip[0].offsetWidth>0,e=b.parents(V).filter(this.tooltip[0]).length>0;b[0]===this.target[0]||b[0]===this.tooltip[0]||e||this.target.has(b[0]).length||!c||this.hide(a)}),"number"==typeof e.hide.inactive&&(this._bind(h,"qtip-"+this.id+"-inactive",p),this._bind(i.add(g),x.inactiveEvents,p,"-inactive")),this._bindEvents(r,s,h,i,n,o),this._bind(h.add(g),"mousemove",function(a){if("number"==typeof e.hide.distance){var b=this.cache.origin||{},c=this.options.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&this.hide(a)}this._storeMouse(a)}),"mouse"===f.target&&f.adjust.mouse&&(e.hide.event&&this._bind(h,["mouseenter","mouseleave"],function(a){this.cache.onTarget="mouseenter"===a.type}),this._bind(l,"mousemove",function(a){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(_)&&this.tooltip[0].offsetWidth>0&&this.reposition(a)})),(f.adjust.resize||k.length)&&this._bind(d.event.special.resize?k:m,"resize",q),f.adjust.scroll&&this._bind(m.add(f.container),"scroll",q)},y._unassignEvents=function(){var c=[this.options.show.target[0],this.options.hide.target[0],this.rendered&&this.tooltip[0],this.options.position.container[0],this.options.position.viewport[0],this.options.position.container.closest("html")[0],a,b];this._unbind(d([]).pushStack(d.grep(c,function(a){return"object"==typeof a})))},x=d.fn.qtip=function(a,b,e){var f=(""+a).toLowerCase(),g=E,i=d.makeArray(arguments).slice(1),j=i[i.length-1],k=this[0]?d.data(this[0],R):E;return!arguments.length&&k||"api"===f?k:"string"==typeof a?(this.each(function(){var a=d.data(this,R);if(!a)return C;if(j&&j.timeStamp&&(a.cache.event=j),!b||"option"!==f&&"options"!==f)a[f]&&a[f].apply(a,i);else{if(e===c&&!d.isPlainObject(b))return g=a.get(b),D;a.set(b,e)}}),g!==E?g:this):"object"!=typeof a&&arguments.length?void 0:(k=h(d.extend(C,{},a)),this.each(function(a){var b,c;return c=d.isArray(k.id)?k.id[a]:k.id,c=!c||c===D||c.length<1||x.api[c]?x.nextid++:c,b=s(d(this),c,k),b===D?C:(x.api[c]=b,d.each(Q,function(){"initialize"===this.initialize&&this(b)}),b._assignInitialEvents(j),void 0)}))},d.qtip=e,x.api={},d.each({attr:function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?d.attr(c,bb):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(bb,b))}return d.fn["attr"+ab].apply(this,arguments)},clone:function(a){var b=(d([]),d.fn["clone"+ab].apply(this,arguments));return a||b.filter("["+bb+"]").attr("title",function(){return d.attr(this,bb)}).removeAttr(bb),b}},function(a,b){if(!b||d.fn[a+ab])return C;var c=d.fn[a+ab]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+ab]=d.cleanData,d.cleanData=function(a){for(var b,c=0;(b=d(a[c])).length;c++)if(b.attr(S))try{b.triggerHandler("removeqtip")}catch(e){}d["cleanData"+ab].apply(this,arguments)}),x.version="2.2.0",x.nextid=0,x.inactiveEvents=W,x.zindex=15e3,x.defaults={prerender:D,id:D,overwrite:C,suppress:C,content:{text:C,attr:"title",title:D,button:D},position:{my:"top left",at:"bottom right",target:D,container:D,viewport:D,adjust:{x:0,y:0,mouse:C,scroll:C,resize:C,method:"flipinvert flipinvert"},effect:function(a,b){d(this).animate(b,{duration:200,queue:D})}},show:{target:D,event:"mouseenter",effect:C,delay:90,solo:D,ready:D,autofocus:D},hide:{target:D,event:"mouseleave",effect:C,delay:0,fixed:D,inactive:D,leave:"window",distance:D},style:{classes:"",widget:D,width:D,height:D,def:C},events:{render:E,move:E,show:E,hide:E,toggle:E,visible:E,hidden:E,focus:E,blur:E}};var hb,ib="margin",jb="border",kb="color",lb="background-color",mb="transparent",nb=" !important",ob=!!b.createElement("canvas").getContext,pb=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,qb={},rb=["Webkit","O","Moz","ms"];if(ob)var sb=a.devicePixelRatio||1,tb=function(){var a=b.createElement("canvas").getContext("2d");return a.backingStorePixelRatio||a.webkitBackingStorePixelRatio||a.mozBackingStorePixelRatio||a.msBackingStorePixelRatio||a.oBackingStorePixelRatio||1}(),ub=sb/tb;else var vb=function(a,b,c){return"'};d.extend(w.prototype,{init:function(a){var b,c;c=this.element=a.elements.tip=d("",{"class":R+"-tip"}).prependTo(a.tooltip),ob?(b=d("").appendTo(this.element)[0].getContext("2d"),b.lineJoin="miter",b.miterLimit=1e5,b.save()):(b=vb("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(b+b),a._bind(d("*",c).add(c),["click","mousedown"],function(a){a.stopPropagation()},this._ns)),a._bind(a.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(a){var b=this.qtip.elements.titlebar;return b&&(a.y===J||a.y===N&&this.element.position().top+this.size[1]/2+this.options.offsetl&&!pb.test(e[1])&&(e[0]=e[1]),this.border=l=p.border!==C?p.border:l):this.border=l=0,k=this.size=this._calculateSize(b),n.css({width:k[0],height:k[1],lineHeight:k[1]+"px"}),j=b.precedance===G?[s(r.x===K?l:r.x===M?k[0]-q[0]-l:(k[0]-q[0])/2),s(r.y===J?k[1]-q[1]:0)]:[s(r.x===K?k[0]-q[0]:0),s(r.y===J?l:r.y===L?k[1]-q[1]-l:(k[1]-q[1])/2)],ob?(g=o[0].getContext("2d"),g.restore(),g.save(),g.clearRect(0,0,6e3,6e3),h=this._calculateTip(r,q,ub),i=this._calculateTip(r,this.size,ub),o.attr(H,k[0]*ub).attr(I,k[1]*ub),o.css(H,k[0]).css(I,k[1]),this._drawCoords(g,i),g.fillStyle=e[1],g.fill(),g.translate(j[0]*ub,j[1]*ub),this._drawCoords(g,h),g.fillStyle=e[0],g.fill()):(h=this._calculateTip(r),h="m"+h[0]+","+h[1]+" l"+h[2]+","+h[3]+" "+h[4]+","+h[5]+" xe",j[2]=l&&/^(r|b)/i.test(b.string())?8===cb.ie?2:1:0,o.css({coordsize:k[0]+l+" "+(k[1]+l),antialias:""+(r.string().indexOf(N)>-1),left:j[0]-j[2]*Number(f===F),top:j[1]-j[2]*Number(f===G),width:k[0]+l,height:k[1]+l}).each(function(a){var b=d(this);b[b.prop?"prop":"attr"]({coordsize:k[0]+l+" "+(k[1]+l),path:h,fillcolor:e[0],filled:!!a,stroked:!a}).toggle(!(!l&&!a)),!a&&b.html(vb("stroke",'weight="'+2*l+'px" color="'+e[1]+'" miterlimit="1000" joinstyle="miter"'))})),a.opera&&setTimeout(function(){m.tip.css({display:"inline-block",visibility:"visible"})},1),c!==D&&this.calculate(b,k)},calculate:function(a,b){if(!this.enabled)return D;var c,e,f=this,g=this.qtip.elements,h=this.element,i=this.options.offset,j=(g.tooltip.hasClass("ui-widget"),{});return a=a||this.corner,c=a.precedance,b=b||this._calculateSize(a),e=[a.x,a.y],c===F&&e.reverse(),d.each(e,function(d,e){var h,k,l;e===N?(h=c===G?K:J,j[h]="50%",j[ib+"-"+h]=-Math.round(b[c===G?0:1]/2)+i):(h=f._parseWidth(a,e,g.tooltip),k=f._parseWidth(a,e,g.content),l=f._parseRadius(a),j[e]=Math.max(-f.border,d?k:i+(l>h?l:-h)))}),j[a[c]]-=b[c===F?0:1],h.css({margin:"",top:"",bottom:"",left:"",right:""}).css(j),j
+},reposition:function(a,b,d){function e(a,b,c,d,e){a===P&&j.precedance===b&&k[d]&&j[c]!==N?j.precedance=j.precedance===F?G:F:a!==P&&k[d]&&(j[b]=j[b]===N?k[d]>0?d:e:j[b]===d?e:d)}function f(a,b,e){j[a]===N?p[ib+"-"+b]=o[a]=g[ib+"-"+b]-k[b]:(h=g[e]!==c?[k[b],-g[b]]:[-k[b],g[b]],(o[a]=Math.max(h[0],h[1]))>h[0]&&(d[b]-=k[b],o[b]=D),p[g[e]!==c?e:b]=o[a])}if(this.enabled){var g,h,i=b.cache,j=this.corner.clone(),k=d.adjusted,l=b.options.position.adjust.method.split(" "),m=l[0],n=l[1]||l[0],o={left:D,top:D,x:0,y:0},p={};this.corner.fixed!==C&&(e(m,F,G,K,M),e(n,G,F,J,L),j.string()===i.corner.string()||i.cornerTop===k.top&&i.cornerLeft===k.left||this.update(j,D)),g=this.calculate(j),g.right!==c&&(g.left=-g.right),g.bottom!==c&&(g.top=-g.bottom),g.user=this.offset,(o.left=m===P&&!!k.left)&&f(F,K,M),(o.top=n===P&&!!k.top)&&f(G,J,L),this.element.css(p).toggle(!(o.x&&o.y||j.x===N&&o.y||j.y===N&&o.x)),d.left-=g.left.charAt?g.user:m!==P||o.top||!o.left&&!o.top?g.left+this.border:0,d.top-=g.top.charAt?g.user:n!==P||o.left||!o.left&&!o.top?g.top+this.border:0,i.cornerLeft=k.left,i.cornerTop=k.top,i.corner=j.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),hb=Q.tip=function(a){return new w(a,a.options.style.tip)},hb.initialize="render",hb.sanitize=function(a){if(a.style&&"tip"in a.style){var b=a.style.tip;"object"!=typeof b&&(b=a.style.tip={corner:b}),/string|boolean/i.test(typeof b.corner)||(b.corner=C)}},A.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(a){this.size=[a.width,a.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},d.extend(C,x.defaults,{style:{tip:{corner:C,mimic:D,width:6,height:6,border:C,offset:0}}}),Q.viewport=function(c,d,e,f,g,h,i){function j(a,b,c,e,f,g,h,i,j){var k=d[f],m=v[a],t=w[a],u=c===P,x=m===f?j:m===g?-j:-j/2,y=t===f?i:t===g?-i:-i/2,z=r[f]+s[f]-(o?0:n[f]),A=z-k,B=k+j-(h===H?p:q)-z,C=x-(v.precedance===a||m===v[b]?y:0)-(t===N?i/2:0);return u?(C=(m===f?1:-1)*x,d[f]+=A>0?A:B>0?-B:0,d[f]=Math.max(-n[f]+s[f],k-C,Math.min(Math.max(-n[f]+s[f]+(h===H?p:q),k+C),d[f],"center"===m?k-x:1e9))):(e*=c===O?2:0,A>0&&(m!==f||B>0)?(d[f]-=C+e,l.invert(a,f)):B>0&&(m!==g||A>0)&&(d[f]-=(m===N?-C:C)+e,l.invert(a,g)),d[f]B&&(d[f]=k,l=v.clone())),d[f]-k}var k,l,m,n,o,p,q,r,s,t=e.target,u=c.elements.tooltip,v=e.my,w=e.at,x=e.adjust,y=x.method.split(" "),z=y[0],A=y[1]||y[0],B=e.viewport,C=e.container,E=c.cache,Q={left:0,top:0};return B.jquery&&t[0]!==a&&t[0]!==b.body&&"none"!==x.method?(n=C.offset()||Q,o="static"===C.css("position"),k="fixed"===u.css("position"),p=B[0]===a?B.width():B.outerWidth(D),q=B[0]===a?B.height():B.outerHeight(D),r={left:k?0:B.scrollLeft(),top:k?0:B.scrollTop()},s=B.offset()||Q,("shift"!==z||"shift"!==A)&&(l=v.clone()),Q={left:"none"!==z?j(F,G,z,x.x,K,M,H,f,h):0,top:"none"!==A?j(G,F,A,x.y,J,L,I,g,i):0},l&&E.lastClass!==(m=R+"-pos-"+l.abbrev())&&u.removeClass(c.cache.lastClass).addClass(c.cache.lastClass=m),Q):Q}})}(window,document);
+//# sourceMappingURL=http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0//var/www/qtip2/build/tmp/tmp-9404f1j0t40/jquery.qtip.min.map
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/js/jquery.scrollto.js b/wp-content/themes/headway/library/admin/js/jquery.scrollto.js
new file mode 100644
index 0000000..5e78778
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/js/jquery.scrollto.js
@@ -0,0 +1,11 @@
+/**
+ * jQuery.ScrollTo - Easy element scrolling using jQuery.
+ * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Dual licensed under MIT and GPL.
+ * Date: 5/25/2009
+ * @author Ariel Flesler
+ * @version 1.4.2
+ *
+ * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
+ */
+;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/admin/js/jquery.tabby.js b/wp-content/themes/headway/library/admin/js/jquery.tabby.js
new file mode 100644
index 0000000..6c36dd4
--- /dev/null
+++ b/wp-content/themes/headway/library/admin/js/jquery.tabby.js
@@ -0,0 +1,8 @@
+/*
+ * Tabby jQuery plugin version 0.12
+ *
+ * Ted Devito - http://teddevito.com/demos/textarea.html
+ *
+ * Copyright (c) 2009 Ted Devito
+ */
+ (function(d){d.fn.tabby=function(f){var g=d.extend({},d.fn.tabby.defaults,f);var h=d.fn.tabby.pressed;return this.each(function(){$this=d(this);var i=d.meta?d.extend({},g,$this.data()):g;$this.bind("keydown",function(k){var j=d.fn.tabby.catch_kc(k);if(16==j){h.shft=true}if(17==j){h.ctrl=true;setTimeout("$.fn.tabby.pressed.ctrl = false;",1000)}if(18==j){h.alt=true;setTimeout("$.fn.tabby.pressed.alt = false;",1000)}if(9==j&&!h.ctrl&&!h.alt){k.preventDefault;h.last=j;setTimeout("$.fn.tabby.pressed.last = null;",0);e(d(k.target).get(0),h.shft,i);return false}}).bind("keyup",function(j){if(16==d.fn.tabby.catch_kc(j)){h.shft=false}}).bind("blur",function(j){if(9==h.last){d(j.target).one("focus",function(k){h.last=null}).get(0).focus()}})})};d.fn.tabby.catch_kc=function(f){return f.keyCode?f.keyCode:f.charCode?f.charCode:f.which};d.fn.tabby.pressed={shft:false,ctrl:false,alt:false,last:null};function b(f){if(window.console&&window.console.log){window.console.log("textarea count: "+f.size())}}function e(i,h,g){var f=i.scrollTop;if(i.setSelectionRange){a(i,h,g)}else{if(document.selection){c(i,h,g)}}i.scrollTop=f}d.fn.tabby.defaults={tabString:String.fromCharCode(9)};function a(j,f,u){var t=j.selectionStart;var r=j.selectionEnd;if(t==r){if(f){if(t-u.tabString==j.value.substring(t-u.tabString.length,t)){j.value=j.value.substring(0,t-u.tabString.length)+j.value.substring(t);j.focus();j.setSelectionRange(t-u.tabString.length,t-u.tabString.length)}else{if(t-u.tabString==j.value.substring(t,t+u.tabString.length)){j.value=j.value.substring(0,t)+j.value.substring(t+u.tabString.length);j.focus();j.setSelectionRange(t,t)}}}else{j.value=j.value.substring(0,t)+u.tabString+j.value.substring(t);j.focus();j.setSelectionRange(t+u.tabString.length,t+u.tabString.length)}}else{while(tt)||(h>=r&<&&h0)?u.tabString.length:(k<0)?-u.tabString.length:0);var m=r+k;j.setSelectionRange(p,m)}}function c(q,w,f){var p=document.selection.createRange();if(q==p.parentElement()){if(""==p.text){if(w){var l=p.getBookmark();p.moveStart("character",-f.tabString.length);if(f.tabString==p.text){p.text=""}else{p.moveToBookmark(l);p.moveEnd("character",f.tabString.length);if(f.tabString==p.text){p.text=""}}p.collapse(true);p.select()}else{p.text=f.tabString;p.collapse(false);p.select()}}else{var k=p.text;var n=k.length;var u=k.split("\r\n");var z=document.body.createTextRange();z.moveToElementText(q);z.setEndPoint("EndToStart",p);var m=z.text;var x=m.split("\r\n");var r=m.length;var y=document.body.createTextRange();y.moveToElementText(q);y.setEndPoint("StartToEnd",p);var v=y.text;var g=document.body.createTextRange();g.moveToElementText(q);g.setEndPoint("StartToEnd",z);var s=g.text;var h=d(q).html();d("#r3").text(r+" + "+n+" + "+v.length+" = "+h.length);if((r+s.length) tag) - put directly in global namespace
+ factory(window['ko'] = {});
+ }
+}(function(koExports){
+// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
+// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
+var ko = typeof koExports !== 'undefined' ? koExports : {};
+// Google Closure Compiler helpers (used only to make the minified file smaller)
+ko.exportSymbol = function(koPath, object) {
+ var tokens = koPath.split(".");
+
+ // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
+ // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
+ var target = ko;
+
+ for (var i = 0; i < tokens.length - 1; i++)
+ target = target[tokens[i]];
+ target[tokens[tokens.length - 1]] = object;
+};
+ko.exportProperty = function(owner, publicName, object) {
+ owner[publicName] = object;
+};
+ko.version = "3.1.0";
+
+ko.exportSymbol('version', ko.version);
+ko.utils = (function () {
+ function objectForEach(obj, action) {
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ action(prop, obj[prop]);
+ }
+ }
+ }
+
+ function extend(target, source) {
+ if (source) {
+ for(var prop in source) {
+ if(source.hasOwnProperty(prop)) {
+ target[prop] = source[prop];
+ }
+ }
+ }
+ return target;
+ }
+
+ function setPrototypeOf(obj, proto) {
+ obj.__proto__ = proto;
+ return obj;
+ }
+
+ var canSetPrototype = ({ __proto__: [] } instanceof Array);
+
+ // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
+ var knownEvents = {}, knownEventTypesByEventName = {};
+ var keyEventTypeName = (navigator && /Firefox\/2/i.test(navigator.userAgent)) ? 'KeyboardEvent' : 'UIEvents';
+ knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
+ knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
+ objectForEach(knownEvents, function(eventType, knownEventsForType) {
+ if (knownEventsForType.length) {
+ for (var i = 0, j = knownEventsForType.length; i < j; i++)
+ knownEventTypesByEventName[knownEventsForType[i]] = eventType;
+ }
+ });
+ var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
+
+ // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
+ // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
+ // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
+ // If there is a future need to detect specific versions of IE10+, we will amend this.
+ var ieVersion = document && (function() {
+ var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
+
+ // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
+ while (
+ div.innerHTML = '',
+ iElems[0]
+ ) {}
+ return version > 4 ? version : undefined;
+ }());
+ var isIe6 = ieVersion === 6,
+ isIe7 = ieVersion === 7;
+
+ function isClickOnCheckableElement(element, eventType) {
+ if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
+ if (eventType.toLowerCase() != "click") return false;
+ var inputType = element.type;
+ return (inputType == "checkbox") || (inputType == "radio");
+ }
+
+ return {
+ fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
+
+ arrayForEach: function (array, action) {
+ for (var i = 0, j = array.length; i < j; i++)
+ action(array[i], i);
+ },
+
+ arrayIndexOf: function (array, item) {
+ if (typeof Array.prototype.indexOf == "function")
+ return Array.prototype.indexOf.call(array, item);
+ for (var i = 0, j = array.length; i < j; i++)
+ if (array[i] === item)
+ return i;
+ return -1;
+ },
+
+ arrayFirst: function (array, predicate, predicateOwner) {
+ for (var i = 0, j = array.length; i < j; i++)
+ if (predicate.call(predicateOwner, array[i], i))
+ return array[i];
+ return null;
+ },
+
+ arrayRemoveItem: function (array, itemToRemove) {
+ var index = ko.utils.arrayIndexOf(array, itemToRemove);
+ if (index > 0) {
+ array.splice(index, 1);
+ }
+ else if (index === 0) {
+ array.shift();
+ }
+ },
+
+ arrayGetDistinctValues: function (array) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++) {
+ if (ko.utils.arrayIndexOf(result, array[i]) < 0)
+ result.push(array[i]);
+ }
+ return result;
+ },
+
+ arrayMap: function (array, mapping) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++)
+ result.push(mapping(array[i], i));
+ return result;
+ },
+
+ arrayFilter: function (array, predicate) {
+ array = array || [];
+ var result = [];
+ for (var i = 0, j = array.length; i < j; i++)
+ if (predicate(array[i], i))
+ result.push(array[i]);
+ return result;
+ },
+
+ arrayPushAll: function (array, valuesToPush) {
+ if (valuesToPush instanceof Array)
+ array.push.apply(array, valuesToPush);
+ else
+ for (var i = 0, j = valuesToPush.length; i < j; i++)
+ array.push(valuesToPush[i]);
+ return array;
+ },
+
+ addOrRemoveItem: function(array, value, included) {
+ var existingEntryIndex = ko.utils.arrayIndexOf(ko.utils.peekObservable(array), value);
+ if (existingEntryIndex < 0) {
+ if (included)
+ array.push(value);
+ } else {
+ if (!included)
+ array.splice(existingEntryIndex, 1);
+ }
+ },
+
+ canSetPrototype: canSetPrototype,
+
+ extend: extend,
+
+ setPrototypeOf: setPrototypeOf,
+
+ setPrototypeOfOrExtend: canSetPrototype ? setPrototypeOf : extend,
+
+ objectForEach: objectForEach,
+
+ objectMap: function(source, mapping) {
+ if (!source)
+ return source;
+ var target = {};
+ for (var prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ target[prop] = mapping(source[prop], prop, source);
+ }
+ }
+ return target;
+ },
+
+ emptyDomNode: function (domNode) {
+ while (domNode.firstChild) {
+ ko.removeNode(domNode.firstChild);
+ }
+ },
+
+ moveCleanedNodesToContainerElement: function(nodes) {
+ // Ensure it's a real array, as we're about to reparent the nodes and
+ // we don't want the underlying collection to change while we're doing that.
+ var nodesArray = ko.utils.makeArray(nodes);
+
+ var container = document.createElement('div');
+ for (var i = 0, j = nodesArray.length; i < j; i++) {
+ container.appendChild(ko.cleanNode(nodesArray[i]));
+ }
+ return container;
+ },
+
+ cloneNodes: function (nodesArray, shouldCleanNodes) {
+ for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
+ var clonedNode = nodesArray[i].cloneNode(true);
+ newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
+ }
+ return newNodesArray;
+ },
+
+ setDomNodeChildren: function (domNode, childNodes) {
+ ko.utils.emptyDomNode(domNode);
+ if (childNodes) {
+ for (var i = 0, j = childNodes.length; i < j; i++)
+ domNode.appendChild(childNodes[i]);
+ }
+ },
+
+ replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
+ var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
+ if (nodesToReplaceArray.length > 0) {
+ var insertionPoint = nodesToReplaceArray[0];
+ var parent = insertionPoint.parentNode;
+ for (var i = 0, j = newNodesArray.length; i < j; i++)
+ parent.insertBefore(newNodesArray[i], insertionPoint);
+ for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
+ ko.removeNode(nodesToReplaceArray[i]);
+ }
+ }
+ },
+
+ fixUpContinuousNodeArray: function(continuousNodeArray, parentNode) {
+ // Before acting on a set of nodes that were previously outputted by a template function, we have to reconcile
+ // them against what is in the DOM right now. It may be that some of the nodes have already been removed, or that
+ // new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
+ // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
+ // So, this function translates the old "map" output array into its best guess of the set of current DOM nodes.
+ //
+ // Rules:
+ // [A] Any leading nodes that have been removed should be ignored
+ // These most likely correspond to memoization nodes that were already removed during binding
+ // See https://github.com/SteveSanderson/knockout/pull/440
+ // [B] We want to output a continuous series of nodes. So, ignore any nodes that have already been removed,
+ // and include any nodes that have been inserted among the previous collection
+
+ if (continuousNodeArray.length) {
+ // The parent node can be a virtual element; so get the real parent node
+ parentNode = (parentNode.nodeType === 8 && parentNode.parentNode) || parentNode;
+
+ // Rule [A]
+ while (continuousNodeArray.length && continuousNodeArray[0].parentNode !== parentNode)
+ continuousNodeArray.shift();
+
+ // Rule [B]
+ if (continuousNodeArray.length > 1) {
+ var current = continuousNodeArray[0], last = continuousNodeArray[continuousNodeArray.length - 1];
+ // Replace with the actual new continuous node set
+ continuousNodeArray.length = 0;
+ while (current !== last) {
+ continuousNodeArray.push(current);
+ current = current.nextSibling;
+ if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
+ return;
+ }
+ continuousNodeArray.push(last);
+ }
+ }
+ return continuousNodeArray;
+ },
+
+ setOptionNodeSelectionState: function (optionNode, isSelected) {
+ // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
+ if (ieVersion < 7)
+ optionNode.setAttribute("selected", isSelected);
+ else
+ optionNode.selected = isSelected;
+ },
+
+ stringTrim: function (string) {
+ return string === null || string === undefined ? '' :
+ string.trim ?
+ string.trim() :
+ string.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
+ },
+
+ stringTokenize: function (string, delimiter) {
+ var result = [];
+ var tokens = (string || "").split(delimiter);
+ for (var i = 0, j = tokens.length; i < j; i++) {
+ var trimmed = ko.utils.stringTrim(tokens[i]);
+ if (trimmed !== "")
+ result.push(trimmed);
+ }
+ return result;
+ },
+
+ stringStartsWith: function (string, startsWith) {
+ string = string || "";
+ if (startsWith.length > string.length)
+ return false;
+ return string.substring(0, startsWith.length) === startsWith;
+ },
+
+ domNodeIsContainedBy: function (node, containedByNode) {
+ if (node === containedByNode)
+ return true;
+ if (node.nodeType === 11)
+ return false; // Fixes issue #1162 - can't use node.contains for document fragments on IE8
+ if (containedByNode.contains)
+ return containedByNode.contains(node.nodeType === 3 ? node.parentNode : node);
+ if (containedByNode.compareDocumentPosition)
+ return (containedByNode.compareDocumentPosition(node) & 16) == 16;
+ while (node && node != containedByNode) {
+ node = node.parentNode;
+ }
+ return !!node;
+ },
+
+ domNodeIsAttachedToDocument: function (node) {
+ return ko.utils.domNodeIsContainedBy(node, node.ownerDocument.documentElement);
+ },
+
+ anyDomNodeIsAttachedToDocument: function(nodes) {
+ return !!ko.utils.arrayFirst(nodes, ko.utils.domNodeIsAttachedToDocument);
+ },
+
+ tagNameLower: function(element) {
+ // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
+ // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
+ // we don't need to do the .toLowerCase() as it will always be lower case anyway.
+ return element && element.tagName && element.tagName.toLowerCase();
+ },
+
+ registerEventHandler: function (element, eventType, handler) {
+ var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
+ if (!mustUseAttachEvent && jQuery) {
+ jQuery(element)['bind'](eventType, handler);
+ } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
+ element.addEventListener(eventType, handler, false);
+ else if (typeof element.attachEvent != "undefined") {
+ var attachEventHandler = function (event) { handler.call(element, event); },
+ attachEventName = "on" + eventType;
+ element.attachEvent(attachEventName, attachEventHandler);
+
+ // IE does not dispose attachEvent handlers automatically (unlike with addEventListener)
+ // so to avoid leaks, we have to remove them manually. See bug #856
+ ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
+ element.detachEvent(attachEventName, attachEventHandler);
+ });
+ } else
+ throw new Error("Browser doesn't support addEventListener or attachEvent");
+ },
+
+ triggerEvent: function (element, eventType) {
+ if (!(element && element.nodeType))
+ throw new Error("element must be a DOM node when calling triggerEvent");
+
+ // For click events on checkboxes and radio buttons, jQuery toggles the element checked state *after* the
+ // event handler runs instead of *before*. (This was fixed in 1.9 for checkboxes but not for radio buttons.)
+ // IE doesn't change the checked state when you trigger the click event using "fireEvent".
+ // In both cases, we'll use the click method instead.
+ var useClickWorkaround = isClickOnCheckableElement(element, eventType);
+
+ if (jQuery && !useClickWorkaround) {
+ jQuery(element)['trigger'](eventType);
+ } else if (typeof document.createEvent == "function") {
+ if (typeof element.dispatchEvent == "function") {
+ var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
+ var event = document.createEvent(eventCategory);
+ event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
+ element.dispatchEvent(event);
+ }
+ else
+ throw new Error("The supplied element doesn't support dispatchEvent");
+ } else if (useClickWorkaround && element.click) {
+ element.click();
+ } else if (typeof element.fireEvent != "undefined") {
+ element.fireEvent("on" + eventType);
+ } else {
+ throw new Error("Browser doesn't support triggering events");
+ }
+ },
+
+ unwrapObservable: function (value) {
+ return ko.isObservable(value) ? value() : value;
+ },
+
+ peekObservable: function (value) {
+ return ko.isObservable(value) ? value.peek() : value;
+ },
+
+ toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
+ if (classNames) {
+ var cssClassNameRegex = /\S+/g,
+ currentClassNames = node.className.match(cssClassNameRegex) || [];
+ ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
+ ko.utils.addOrRemoveItem(currentClassNames, className, shouldHaveClass);
+ });
+ node.className = currentClassNames.join(" ");
+ }
+ },
+
+ setTextContent: function(element, textContent) {
+ var value = ko.utils.unwrapObservable(textContent);
+ if ((value === null) || (value === undefined))
+ value = "";
+
+ // We need there to be exactly one child: a text node.
+ // If there are no children, more than one, or if it's not a text node,
+ // we'll clear everything and create a single text node.
+ var innerTextNode = ko.virtualElements.firstChild(element);
+ if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
+ ko.virtualElements.setDomNodeChildren(element, [element.ownerDocument.createTextNode(value)]);
+ } else {
+ innerTextNode.data = value;
+ }
+
+ ko.utils.forceRefresh(element);
+ },
+
+ setElementName: function(element, name) {
+ element.name = name;
+
+ // Workaround IE 6/7 issue
+ // - https://github.com/SteveSanderson/knockout/issues/197
+ // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
+ if (ieVersion <= 7) {
+ try {
+ element.mergeAttributes(document.createElement(""), false);
+ }
+ catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
+ }
+ },
+
+ forceRefresh: function(node) {
+ // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
+ if (ieVersion >= 9) {
+ // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
+ var elem = node.nodeType == 1 ? node : node.parentNode;
+ if (elem.style)
+ elem.style.zoom = elem.style.zoom;
+ }
+ },
+
+ ensureSelectElementIsRenderedCorrectly: function(selectElement) {
+ // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
+ // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
+ // Also fixes IE7 and IE8 bug that causes selects to be zero width if enclosed by 'if' or 'with'. (See issue #839)
+ if (ieVersion) {
+ var originalWidth = selectElement.style.width;
+ selectElement.style.width = 0;
+ selectElement.style.width = originalWidth;
+ }
+ },
+
+ range: function (min, max) {
+ min = ko.utils.unwrapObservable(min);
+ max = ko.utils.unwrapObservable(max);
+ var result = [];
+ for (var i = min; i <= max; i++)
+ result.push(i);
+ return result;
+ },
+
+ makeArray: function(arrayLikeObject) {
+ var result = [];
+ for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
+ result.push(arrayLikeObject[i]);
+ };
+ return result;
+ },
+
+ isIe6 : isIe6,
+ isIe7 : isIe7,
+ ieVersion : ieVersion,
+
+ getFormFields: function(form, fieldName) {
+ var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
+ var isMatchingField = (typeof fieldName == 'string')
+ ? function(field) { return field.name === fieldName }
+ : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
+ var matches = [];
+ for (var i = fields.length - 1; i >= 0; i--) {
+ if (isMatchingField(fields[i]))
+ matches.push(fields[i]);
+ };
+ return matches;
+ },
+
+ parseJson: function (jsonString) {
+ if (typeof jsonString == "string") {
+ jsonString = ko.utils.stringTrim(jsonString);
+ if (jsonString) {
+ if (JSON && JSON.parse) // Use native parsing where available
+ return JSON.parse(jsonString);
+ return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
+ }
+ }
+ return null;
+ },
+
+ stringifyJson: function (data, replacer, space) { // replacer and space are optional
+ if (!JSON || !JSON.stringify)
+ throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
+ return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
+ },
+
+ postJson: function (urlOrForm, data, options) {
+ options = options || {};
+ var params = options['params'] || {};
+ var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
+ var url = urlOrForm;
+
+ // If we were given a form, use its 'action' URL and pick out any requested field values
+ if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
+ var originalForm = urlOrForm;
+ url = originalForm.action;
+ for (var i = includeFields.length - 1; i >= 0; i--) {
+ var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
+ for (var j = fields.length - 1; j >= 0; j--)
+ params[fields[j].name] = fields[j].value;
+ }
+ }
+
+ data = ko.utils.unwrapObservable(data);
+ var form = document.createElement("form");
+ form.style.display = "none";
+ form.action = url;
+ form.method = "post";
+ for (var key in data) {
+ // Since 'data' this is a model object, we include all properties including those inherited from its prototype
+ var input = document.createElement("input");
+ input.name = key;
+ input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
+ form.appendChild(input);
+ }
+ objectForEach(params, function(key, value) {
+ var input = document.createElement("input");
+ input.name = key;
+ input.value = value;
+ form.appendChild(input);
+ });
+ document.body.appendChild(form);
+ options['submitter'] ? options['submitter'](form) : form.submit();
+ setTimeout(function () { form.parentNode.removeChild(form); }, 0);
+ }
+ }
+}());
+
+ko.exportSymbol('utils', ko.utils);
+ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
+ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
+ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
+ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
+ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
+ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
+ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
+ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
+ko.exportSymbol('utils.extend', ko.utils.extend);
+ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
+ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
+ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
+ko.exportSymbol('utils.postJson', ko.utils.postJson);
+ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
+ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
+ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
+ko.exportSymbol('utils.range', ko.utils.range);
+ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
+ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
+ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
+ko.exportSymbol('utils.objectForEach', ko.utils.objectForEach);
+ko.exportSymbol('utils.addOrRemoveItem', ko.utils.addOrRemoveItem);
+ko.exportSymbol('unwrap', ko.utils.unwrapObservable); // Convenient shorthand, because this is used so commonly
+
+if (!Function.prototype['bind']) {
+ // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
+ // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
+ Function.prototype['bind'] = function (object) {
+ var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
+ return function () {
+ return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
+ };
+ };
+}
+
+ko.utils.domData = new (function () {
+ var uniqueId = 0;
+ var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
+ var dataStore = {};
+
+ function getAll(node, createIfNotFound) {
+ var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
+ var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
+ if (!hasExistingDataStore) {
+ if (!createIfNotFound)
+ return undefined;
+ dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
+ dataStore[dataStoreKey] = {};
+ }
+ return dataStore[dataStoreKey];
+ }
+
+ return {
+ get: function (node, key) {
+ var allDataForNode = getAll(node, false);
+ return allDataForNode === undefined ? undefined : allDataForNode[key];
+ },
+ set: function (node, key, value) {
+ if (value === undefined) {
+ // Make sure we don't actually create a new domData key if we are actually deleting a value
+ if (getAll(node, false) === undefined)
+ return;
+ }
+ var allDataForNode = getAll(node, true);
+ allDataForNode[key] = value;
+ },
+ clear: function (node) {
+ var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
+ if (dataStoreKey) {
+ delete dataStore[dataStoreKey];
+ node[dataStoreKeyExpandoPropertyName] = null;
+ return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
+ }
+ return false;
+ },
+
+ nextKey: function () {
+ return (uniqueId++) + dataStoreKeyExpandoPropertyName;
+ }
+ };
+})();
+
+ko.exportSymbol('utils.domData', ko.utils.domData);
+ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
+
+ko.utils.domNodeDisposal = new (function () {
+ var domDataKey = ko.utils.domData.nextKey();
+ var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
+ var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
+
+ function getDisposeCallbacksCollection(node, createIfNotFound) {
+ var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
+ if ((allDisposeCallbacks === undefined) && createIfNotFound) {
+ allDisposeCallbacks = [];
+ ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
+ }
+ return allDisposeCallbacks;
+ }
+ function destroyCallbacksCollection(node) {
+ ko.utils.domData.set(node, domDataKey, undefined);
+ }
+
+ function cleanSingleNode(node) {
+ // Run all the dispose callbacks
+ var callbacks = getDisposeCallbacksCollection(node, false);
+ if (callbacks) {
+ callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
+ for (var i = 0; i < callbacks.length; i++)
+ callbacks[i](node);
+ }
+
+ // Erase the DOM data
+ ko.utils.domData.clear(node);
+
+ // Perform cleanup needed by external libraries (currently only jQuery, but can be extended)
+ ko.utils.domNodeDisposal["cleanExternalData"](node);
+
+ // Clear any immediate-child comment nodes, as these wouldn't have been found by
+ // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
+ if (cleanableNodeTypesWithDescendants[node.nodeType])
+ cleanImmediateCommentTypeChildren(node);
+ }
+
+ function cleanImmediateCommentTypeChildren(nodeWithChildren) {
+ var child, nextChild = nodeWithChildren.firstChild;
+ while (child = nextChild) {
+ nextChild = child.nextSibling;
+ if (child.nodeType === 8)
+ cleanSingleNode(child);
+ }
+ }
+
+ return {
+ addDisposeCallback : function(node, callback) {
+ if (typeof callback != "function")
+ throw new Error("Callback must be a function");
+ getDisposeCallbacksCollection(node, true).push(callback);
+ },
+
+ removeDisposeCallback : function(node, callback) {
+ var callbacksCollection = getDisposeCallbacksCollection(node, false);
+ if (callbacksCollection) {
+ ko.utils.arrayRemoveItem(callbacksCollection, callback);
+ if (callbacksCollection.length == 0)
+ destroyCallbacksCollection(node);
+ }
+ },
+
+ cleanNode : function(node) {
+ // First clean this node, where applicable
+ if (cleanableNodeTypes[node.nodeType]) {
+ cleanSingleNode(node);
+
+ // ... then its descendants, where applicable
+ if (cleanableNodeTypesWithDescendants[node.nodeType]) {
+ // Clone the descendants list in case it changes during iteration
+ var descendants = [];
+ ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
+ for (var i = 0, j = descendants.length; i < j; i++)
+ cleanSingleNode(descendants[i]);
+ }
+ }
+ return node;
+ },
+
+ removeNode : function(node) {
+ ko.cleanNode(node);
+ if (node.parentNode)
+ node.parentNode.removeChild(node);
+ },
+
+ "cleanExternalData" : function (node) {
+ // Special support for jQuery here because it's so commonly used.
+ // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
+ // so notify it to tear down any resources associated with the node & descendants here.
+ if (jQuery && (typeof jQuery['cleanData'] == "function"))
+ jQuery['cleanData']([node]);
+ }
+ }
+})();
+ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
+ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
+ko.exportSymbol('cleanNode', ko.cleanNode);
+ko.exportSymbol('removeNode', ko.removeNode);
+ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
+ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
+ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
+(function () {
+ var leadingCommentRegex = /^(\s*)/;
+
+ function simpleHtmlParse(html) {
+ // Based on jQuery's "clean" function, but only accounting for table-related elements.
+ // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
+
+ // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
+ // a descendant node. For example: "
abc
" will get parsed as "
abc
"
+ // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
+ // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
+
+ // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
+ var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "
", "
"] ||
+ !tags.indexOf("
", ""] ||
+ (!tags.indexOf("
", "
"] ||
+ /* anything else */ [0, "", ""];
+
+ // Go to html and back, then peel off extra wrappers
+ // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
+ var markup = "ignored
" + wrap[1] + html + wrap[2] + "
";
+ if (typeof window['innerShiv'] == "function") {
+ div.appendChild(window['innerShiv'](markup));
+ } else {
+ div.innerHTML = markup;
+ }
+
+ // Move to the right depth
+ while (wrap[0]--)
+ div = div.lastChild;
+
+ return ko.utils.makeArray(div.lastChild.childNodes);
+ }
+
+ function jQueryHtmlParse(html) {
+ // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
+ if (jQuery['parseHTML']) {
+ return jQuery['parseHTML'](html) || []; // Ensure we always return an array and never null
+ } else {
+ // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
+ var elems = jQuery['clean']([html]);
+
+ // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
+ // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
+ // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
+ if (elems && elems[0]) {
+ // Find the top-most parent element that's a direct child of a document fragment
+ var elem = elems[0];
+ while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
+ elem = elem.parentNode;
+ // ... then detach it
+ if (elem.parentNode)
+ elem.parentNode.removeChild(elem);
+ }
+
+ return elems;
+ }
+ }
+
+ ko.utils.parseHtmlFragment = function(html) {
+ return jQuery ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
+ : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
+ };
+
+ ko.utils.setHtml = function(node, html) {
+ ko.utils.emptyDomNode(node);
+
+ // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
+ html = ko.utils.unwrapObservable(html);
+
+ if ((html !== null) && (html !== undefined)) {
+ if (typeof html != 'string')
+ html = html.toString();
+
+ // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
+ // for example
elements which are not normally allowed to exist on their own.
+ // If you've referenced jQuery we'll use that rather than duplicating its code.
+ if (jQuery) {
+ jQuery(node)['html'](html);
+ } else {
+ // ... otherwise, use KO's own parsing logic.
+ var parsedNodes = ko.utils.parseHtmlFragment(html);
+ for (var i = 0; i < parsedNodes.length; i++)
+ node.appendChild(parsedNodes[i]);
+ }
+ }
+ };
+})();
+
+ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
+ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
+
+ko.memoization = (function () {
+ var memos = {};
+
+ function randomMax8HexChars() {
+ return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
+ }
+ function generateRandomId() {
+ return randomMax8HexChars() + randomMax8HexChars();
+ }
+ function findMemoNodes(rootNode, appendToArray) {
+ if (!rootNode)
+ return;
+ if (rootNode.nodeType == 8) {
+ var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
+ if (memoId != null)
+ appendToArray.push({ domNode: rootNode, memoId: memoId });
+ } else if (rootNode.nodeType == 1) {
+ for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
+ findMemoNodes(childNodes[i], appendToArray);
+ }
+ }
+
+ return {
+ memoize: function (callback) {
+ if (typeof callback != "function")
+ throw new Error("You can only pass a function to ko.memoization.memoize()");
+ var memoId = generateRandomId();
+ memos[memoId] = callback;
+ return "";
+ },
+
+ unmemoize: function (memoId, callbackParams) {
+ var callback = memos[memoId];
+ if (callback === undefined)
+ throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
+ try {
+ callback.apply(null, callbackParams || []);
+ return true;
+ }
+ finally { delete memos[memoId]; }
+ },
+
+ unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
+ var memos = [];
+ findMemoNodes(domNode, memos);
+ for (var i = 0, j = memos.length; i < j; i++) {
+ var node = memos[i].domNode;
+ var combinedParams = [node];
+ if (extraCallbackParamsArray)
+ ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
+ ko.memoization.unmemoize(memos[i].memoId, combinedParams);
+ node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
+ if (node.parentNode)
+ node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
+ }
+ },
+
+ parseMemoText: function (memoText) {
+ var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
+ return match ? match[1] : null;
+ }
+ };
+})();
+
+ko.exportSymbol('memoization', ko.memoization);
+ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
+ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
+ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
+ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
+ko.extenders = {
+ 'throttle': function(target, timeout) {
+ // Throttling means two things:
+
+ // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
+ // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
+ target['throttleEvaluation'] = timeout;
+
+ // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
+ // so the target cannot change value synchronously or faster than a certain rate
+ var writeTimeoutInstance = null;
+ return ko.dependentObservable({
+ 'read': target,
+ 'write': function(value) {
+ clearTimeout(writeTimeoutInstance);
+ writeTimeoutInstance = setTimeout(function() {
+ target(value);
+ }, timeout);
+ }
+ });
+ },
+
+ 'rateLimit': function(target, options) {
+ var timeout, method, limitFunction;
+
+ if (typeof options == 'number') {
+ timeout = options;
+ } else {
+ timeout = options['timeout'];
+ method = options['method'];
+ }
+
+ limitFunction = method == 'notifyWhenChangesStop' ? debounce : throttle;
+ target.limit(function(callback) {
+ return limitFunction(callback, timeout);
+ });
+ },
+
+ 'notify': function(target, notifyWhen) {
+ target["equalityComparer"] = notifyWhen == "always" ?
+ null : // null equalityComparer means to always notify
+ valuesArePrimitiveAndEqual;
+ }
+};
+
+var primitiveTypes = { 'undefined':1, 'boolean':1, 'number':1, 'string':1 };
+function valuesArePrimitiveAndEqual(a, b) {
+ var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
+ return oldValueIsPrimitive ? (a === b) : false;
+}
+
+function throttle(callback, timeout) {
+ var timeoutInstance;
+ return function () {
+ if (!timeoutInstance) {
+ timeoutInstance = setTimeout(function() {
+ timeoutInstance = undefined;
+ callback();
+ }, timeout);
+ }
+ };
+}
+
+function debounce(callback, timeout) {
+ var timeoutInstance;
+ return function () {
+ clearTimeout(timeoutInstance);
+ timeoutInstance = setTimeout(callback, timeout);
+ };
+}
+
+function applyExtenders(requestedExtenders) {
+ var target = this;
+ if (requestedExtenders) {
+ ko.utils.objectForEach(requestedExtenders, function(key, value) {
+ var extenderHandler = ko.extenders[key];
+ if (typeof extenderHandler == 'function') {
+ target = extenderHandler(target, value) || target;
+ }
+ });
+ }
+ return target;
+}
+
+ko.exportSymbol('extenders', ko.extenders);
+
+ko.subscription = function (target, callback, disposeCallback) {
+ this.target = target;
+ this.callback = callback;
+ this.disposeCallback = disposeCallback;
+ this.isDisposed = false;
+ ko.exportProperty(this, 'dispose', this.dispose);
+};
+ko.subscription.prototype.dispose = function () {
+ this.isDisposed = true;
+ this.disposeCallback();
+};
+
+ko.subscribable = function () {
+ ko.utils.setPrototypeOfOrExtend(this, ko.subscribable['fn']);
+ this._subscriptions = {};
+}
+
+var defaultEvent = "change";
+
+var ko_subscribable_fn = {
+ subscribe: function (callback, callbackTarget, event) {
+ var self = this;
+
+ event = event || defaultEvent;
+ var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
+
+ var subscription = new ko.subscription(self, boundCallback, function () {
+ ko.utils.arrayRemoveItem(self._subscriptions[event], subscription);
+ });
+
+ // This will force a computed with deferEvaluation to evaluate before any subscriptions
+ // are registered.
+ if (self.peek) {
+ self.peek();
+ }
+
+ if (!self._subscriptions[event])
+ self._subscriptions[event] = [];
+ self._subscriptions[event].push(subscription);
+ return subscription;
+ },
+
+ "notifySubscribers": function (valueToNotify, event) {
+ event = event || defaultEvent;
+ if (this.hasSubscriptionsForEvent(event)) {
+ try {
+ ko.dependencyDetection.begin(); // Begin suppressing dependency detection (by setting the top frame to undefined)
+ for (var a = this._subscriptions[event].slice(0), i = 0, subscription; subscription = a[i]; ++i) {
+ // In case a subscription was disposed during the arrayForEach cycle, check
+ // for isDisposed on each subscription before invoking its callback
+ if (!subscription.isDisposed)
+ subscription.callback(valueToNotify);
+ }
+ } finally {
+ ko.dependencyDetection.end(); // End suppressing dependency detection
+ }
+ }
+ },
+
+ limit: function(limitFunction) {
+ var self = this, selfIsObservable = ko.isObservable(self),
+ isPending, previousValue, pendingValue, beforeChange = 'beforeChange';
+
+ if (!self._origNotifySubscribers) {
+ self._origNotifySubscribers = self["notifySubscribers"];
+ self["notifySubscribers"] = function(value, event) {
+ if (!event || event === defaultEvent) {
+ self._rateLimitedChange(value);
+ } else if (event === beforeChange) {
+ self._rateLimitedBeforeChange(value);
+ } else {
+ self._origNotifySubscribers(value, event);
+ }
+ };
+ }
+
+ var finish = limitFunction(function() {
+ // If an observable provided a reference to itself, access it to get the latest value.
+ // This allows computed observables to delay calculating their value until needed.
+ if (selfIsObservable && pendingValue === self) {
+ pendingValue = self();
+ }
+ isPending = false;
+ if (self.isDifferent(previousValue, pendingValue)) {
+ self._origNotifySubscribers(previousValue = pendingValue);
+ }
+ });
+
+ self._rateLimitedChange = function(value) {
+ isPending = true;
+ pendingValue = value;
+ finish();
+ };
+ self._rateLimitedBeforeChange = function(value) {
+ if (!isPending) {
+ previousValue = value;
+ self._origNotifySubscribers(value, beforeChange);
+ }
+ };
+ },
+
+ hasSubscriptionsForEvent: function(event) {
+ return this._subscriptions[event] && this._subscriptions[event].length;
+ },
+
+ getSubscriptionsCount: function () {
+ var total = 0;
+ ko.utils.objectForEach(this._subscriptions, function(eventName, subscriptions) {
+ total += subscriptions.length;
+ });
+ return total;
+ },
+
+ isDifferent: function(oldValue, newValue) {
+ return !this['equalityComparer'] || !this['equalityComparer'](oldValue, newValue);
+ },
+
+ extend: applyExtenders
+};
+
+ko.exportProperty(ko_subscribable_fn, 'subscribe', ko_subscribable_fn.subscribe);
+ko.exportProperty(ko_subscribable_fn, 'extend', ko_subscribable_fn.extend);
+ko.exportProperty(ko_subscribable_fn, 'getSubscriptionsCount', ko_subscribable_fn.getSubscriptionsCount);
+
+// For browsers that support proto assignment, we overwrite the prototype of each
+// observable instance. Since observables are functions, we need Function.prototype
+// to still be in the prototype chain.
+if (ko.utils.canSetPrototype) {
+ ko.utils.setPrototypeOf(ko_subscribable_fn, Function.prototype);
+}
+
+ko.subscribable['fn'] = ko_subscribable_fn;
+
+
+ko.isSubscribable = function (instance) {
+ return instance != null && typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
+};
+
+ko.exportSymbol('subscribable', ko.subscribable);
+ko.exportSymbol('isSubscribable', ko.isSubscribable);
+
+ko.computedContext = ko.dependencyDetection = (function () {
+ var outerFrames = [],
+ currentFrame,
+ lastId = 0;
+
+ // Return a unique ID that can be assigned to an observable for dependency tracking.
+ // Theoretically, you could eventually overflow the number storage size, resulting
+ // in duplicate IDs. But in JavaScript, the largest exact integral value is 2^53
+ // or 9,007,199,254,740,992. If you created 1,000,000 IDs per second, it would
+ // take over 285 years to reach that number.
+ // Reference http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
+ function getId() {
+ return ++lastId;
+ }
+
+ function begin(options) {
+ outerFrames.push(currentFrame);
+ currentFrame = options;
+ }
+
+ function end() {
+ currentFrame = outerFrames.pop();
+ }
+
+ return {
+ begin: begin,
+
+ end: end,
+
+ registerDependency: function (subscribable) {
+ if (currentFrame) {
+ if (!ko.isSubscribable(subscribable))
+ throw new Error("Only subscribable things can act as dependencies");
+ currentFrame.callback(subscribable, subscribable._id || (subscribable._id = getId()));
+ }
+ },
+
+ ignore: function (callback, callbackTarget, callbackArgs) {
+ try {
+ begin();
+ return callback.apply(callbackTarget, callbackArgs || []);
+ } finally {
+ end();
+ }
+ },
+
+ getDependenciesCount: function () {
+ if (currentFrame)
+ return currentFrame.computed.getDependenciesCount();
+ },
+
+ isInitial: function() {
+ if (currentFrame)
+ return currentFrame.isInitial;
+ }
+ };
+})();
+
+ko.exportSymbol('computedContext', ko.computedContext);
+ko.exportSymbol('computedContext.getDependenciesCount', ko.computedContext.getDependenciesCount);
+ko.exportSymbol('computedContext.isInitial', ko.computedContext.isInitial);
+ko.observable = function (initialValue) {
+ var _latestValue = initialValue;
+
+ function observable() {
+ if (arguments.length > 0) {
+ // Write
+
+ // Ignore writes if the value hasn't changed
+ if (observable.isDifferent(_latestValue, arguments[0])) {
+ observable.valueWillMutate();
+ _latestValue = arguments[0];
+ if (DEBUG) observable._latestValue = _latestValue;
+ observable.valueHasMutated();
+ }
+ return this; // Permits chained assignments
+ }
+ else {
+ // Read
+ ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
+ return _latestValue;
+ }
+ }
+ ko.subscribable.call(observable);
+ ko.utils.setPrototypeOfOrExtend(observable, ko.observable['fn']);
+
+ if (DEBUG) observable._latestValue = _latestValue;
+ observable.peek = function() { return _latestValue };
+ observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
+ observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
+
+ ko.exportProperty(observable, 'peek', observable.peek);
+ ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
+ ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
+
+ return observable;
+}
+
+ko.observable['fn'] = {
+ "equalityComparer": valuesArePrimitiveAndEqual
+};
+
+var protoProperty = ko.observable.protoProperty = "__ko_proto__";
+ko.observable['fn'][protoProperty] = ko.observable;
+
+// Note that for browsers that don't support proto assignment, the
+// inheritance chain is created manually in the ko.observable constructor
+if (ko.utils.canSetPrototype) {
+ ko.utils.setPrototypeOf(ko.observable['fn'], ko.subscribable['fn']);
+}
+
+ko.hasPrototype = function(instance, prototype) {
+ if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
+ if (instance[protoProperty] === prototype) return true;
+ return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
+};
+
+ko.isObservable = function (instance) {
+ return ko.hasPrototype(instance, ko.observable);
+}
+ko.isWriteableObservable = function (instance) {
+ // Observable
+ if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
+ return true;
+ // Writeable dependent observable
+ if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
+ return true;
+ // Anything else
+ return false;
+}
+
+
+ko.exportSymbol('observable', ko.observable);
+ko.exportSymbol('isObservable', ko.isObservable);
+ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
+ko.observableArray = function (initialValues) {
+ initialValues = initialValues || [];
+
+ if (typeof initialValues != 'object' || !('length' in initialValues))
+ throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
+
+ var result = ko.observable(initialValues);
+ ko.utils.setPrototypeOfOrExtend(result, ko.observableArray['fn']);
+ return result.extend({'trackArrayChanges':true});
+};
+
+ko.observableArray['fn'] = {
+ 'remove': function (valueOrPredicate) {
+ var underlyingArray = this.peek();
+ var removedValues = [];
+ var predicate = typeof valueOrPredicate == "function" && !ko.isObservable(valueOrPredicate) ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
+ for (var i = 0; i < underlyingArray.length; i++) {
+ var value = underlyingArray[i];
+ if (predicate(value)) {
+ if (removedValues.length === 0) {
+ this.valueWillMutate();
+ }
+ removedValues.push(value);
+ underlyingArray.splice(i, 1);
+ i--;
+ }
+ }
+ if (removedValues.length) {
+ this.valueHasMutated();
+ }
+ return removedValues;
+ },
+
+ 'removeAll': function (arrayOfValues) {
+ // If you passed zero args, we remove everything
+ if (arrayOfValues === undefined) {
+ var underlyingArray = this.peek();
+ var allValues = underlyingArray.slice(0);
+ this.valueWillMutate();
+ underlyingArray.splice(0, underlyingArray.length);
+ this.valueHasMutated();
+ return allValues;
+ }
+ // If you passed an arg, we interpret it as an array of entries to remove
+ if (!arrayOfValues)
+ return [];
+ return this['remove'](function (value) {
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
+ });
+ },
+
+ 'destroy': function (valueOrPredicate) {
+ var underlyingArray = this.peek();
+ var predicate = typeof valueOrPredicate == "function" && !ko.isObservable(valueOrPredicate) ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
+ this.valueWillMutate();
+ for (var i = underlyingArray.length - 1; i >= 0; i--) {
+ var value = underlyingArray[i];
+ if (predicate(value))
+ underlyingArray[i]["_destroy"] = true;
+ }
+ this.valueHasMutated();
+ },
+
+ 'destroyAll': function (arrayOfValues) {
+ // If you passed zero args, we destroy everything
+ if (arrayOfValues === undefined)
+ return this['destroy'](function() { return true });
+
+ // If you passed an arg, we interpret it as an array of entries to destroy
+ if (!arrayOfValues)
+ return [];
+ return this['destroy'](function (value) {
+ return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
+ });
+ },
+
+ 'indexOf': function (item) {
+ var underlyingArray = this();
+ return ko.utils.arrayIndexOf(underlyingArray, item);
+ },
+
+ 'replace': function(oldItem, newItem) {
+ var index = this['indexOf'](oldItem);
+ if (index >= 0) {
+ this.valueWillMutate();
+ this.peek()[index] = newItem;
+ this.valueHasMutated();
+ }
+ }
+};
+
+// Populate ko.observableArray.fn with read/write functions from native arrays
+// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
+// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
+ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
+ ko.observableArray['fn'][methodName] = function () {
+ // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
+ // (for consistency with mutating regular observables)
+ var underlyingArray = this.peek();
+ this.valueWillMutate();
+ this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments);
+ var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
+ this.valueHasMutated();
+ return methodCallResult;
+ };
+});
+
+// Populate ko.observableArray.fn with read-only functions from native arrays
+ko.utils.arrayForEach(["slice"], function (methodName) {
+ ko.observableArray['fn'][methodName] = function () {
+ var underlyingArray = this();
+ return underlyingArray[methodName].apply(underlyingArray, arguments);
+ };
+});
+
+// Note that for browsers that don't support proto assignment, the
+// inheritance chain is created manually in the ko.observableArray constructor
+if (ko.utils.canSetPrototype) {
+ ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);
+}
+
+ko.exportSymbol('observableArray', ko.observableArray);
+var arrayChangeEventName = 'arrayChange';
+ko.extenders['trackArrayChanges'] = function(target) {
+ // Only modify the target observable once
+ if (target.cacheDiffForKnownOperation) {
+ return;
+ }
+ var trackingChanges = false,
+ cachedDiff = null,
+ pendingNotifications = 0,
+ underlyingSubscribeFunction = target.subscribe;
+
+ // Intercept "subscribe" calls, and for array change events, ensure change tracking is enabled
+ target.subscribe = target['subscribe'] = function(callback, callbackTarget, event) {
+ if (event === arrayChangeEventName) {
+ trackChanges();
+ }
+ return underlyingSubscribeFunction.apply(this, arguments);
+ };
+
+ function trackChanges() {
+ // Calling 'trackChanges' multiple times is the same as calling it once
+ if (trackingChanges) {
+ return;
+ }
+
+ trackingChanges = true;
+
+ // Intercept "notifySubscribers" to track how many times it was called.
+ var underlyingNotifySubscribersFunction = target['notifySubscribers'];
+ target['notifySubscribers'] = function(valueToNotify, event) {
+ if (!event || event === defaultEvent) {
+ ++pendingNotifications;
+ }
+ return underlyingNotifySubscribersFunction.apply(this, arguments);
+ };
+
+ // Each time the array changes value, capture a clone so that on the next
+ // change it's possible to produce a diff
+ var previousContents = [].concat(target.peek() || []);
+ cachedDiff = null;
+ target.subscribe(function(currentContents) {
+ // Make a copy of the current contents and ensure it's an array
+ currentContents = [].concat(currentContents || []);
+
+ // Compute the diff and issue notifications, but only if someone is listening
+ if (target.hasSubscriptionsForEvent(arrayChangeEventName)) {
+ var changes = getChanges(previousContents, currentContents);
+ if (changes.length) {
+ target['notifySubscribers'](changes, arrayChangeEventName);
+ }
+ }
+
+ // Eliminate references to the old, removed items, so they can be GCed
+ previousContents = currentContents;
+ cachedDiff = null;
+ pendingNotifications = 0;
+ });
+ }
+
+ function getChanges(previousContents, currentContents) {
+ // We try to re-use cached diffs.
+ // The scenarios where pendingNotifications > 1 are when using rate-limiting or the Deferred Updates
+ // plugin, which without this check would not be compatible with arrayChange notifications. Normally,
+ // notifications are issued immediately so we wouldn't be queueing up more than one.
+ if (!cachedDiff || pendingNotifications > 1) {
+ cachedDiff = ko.utils.compareArrays(previousContents, currentContents, { 'sparse': true });
+ }
+
+ return cachedDiff;
+ }
+
+ target.cacheDiffForKnownOperation = function(rawArray, operationName, args) {
+ // Only run if we're currently tracking changes for this observable array
+ // and there aren't any pending deferred notifications.
+ if (!trackingChanges || pendingNotifications) {
+ return;
+ }
+ var diff = [],
+ arrayLength = rawArray.length,
+ argsLength = args.length,
+ offset = 0;
+
+ function pushDiff(status, value, index) {
+ return diff[diff.length] = { 'status': status, 'value': value, 'index': index };
+ }
+ switch (operationName) {
+ case 'push':
+ offset = arrayLength;
+ case 'unshift':
+ for (var index = 0; index < argsLength; index++) {
+ pushDiff('added', args[index], offset + index);
+ }
+ break;
+
+ case 'pop':
+ offset = arrayLength - 1;
+ case 'shift':
+ if (arrayLength) {
+ pushDiff('deleted', rawArray[offset], offset);
+ }
+ break;
+
+ case 'splice':
+ // Negative start index means 'from end of array'. After that we clamp to [0...arrayLength].
+ // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
+ var startIndex = Math.min(Math.max(0, args[0] < 0 ? arrayLength + args[0] : args[0]), arrayLength),
+ endDeleteIndex = argsLength === 1 ? arrayLength : Math.min(startIndex + (args[1] || 0), arrayLength),
+ endAddIndex = startIndex + argsLength - 2,
+ endIndex = Math.max(endDeleteIndex, endAddIndex),
+ additions = [], deletions = [];
+ for (var index = startIndex, argsIndex = 2; index < endIndex; ++index, ++argsIndex) {
+ if (index < endDeleteIndex)
+ deletions.push(pushDiff('deleted', rawArray[index], index));
+ if (index < endAddIndex)
+ additions.push(pushDiff('added', args[argsIndex], index));
+ }
+ ko.utils.findMovesInArrayComparison(deletions, additions);
+ break;
+
+ default:
+ return;
+ }
+ cachedDiff = diff;
+ };
+};
+ko.computed = ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
+ var _latestValue,
+ _needsEvaluation = true,
+ _isBeingEvaluated = false,
+ _suppressDisposalUntilDisposeWhenReturnsFalse = false,
+ _isDisposed = false,
+ readFunction = evaluatorFunctionOrOptions;
+
+ if (readFunction && typeof readFunction == "object") {
+ // Single-parameter syntax - everything is on this "options" param
+ options = readFunction;
+ readFunction = options["read"];
+ } else {
+ // Multi-parameter syntax - construct the options according to the params passed
+ options = options || {};
+ if (!readFunction)
+ readFunction = options["read"];
+ }
+ if (typeof readFunction != "function")
+ throw new Error("Pass a function that returns the value of the ko.computed");
+
+ function addSubscriptionToDependency(subscribable, id) {
+ if (!_subscriptionsToDependencies[id]) {
+ _subscriptionsToDependencies[id] = subscribable.subscribe(evaluatePossiblyAsync);
+ ++_dependenciesCount;
+ }
+ }
+
+ function disposeAllSubscriptionsToDependencies() {
+ _isDisposed = true;
+ ko.utils.objectForEach(_subscriptionsToDependencies, function (id, subscription) {
+ subscription.dispose();
+ });
+ _subscriptionsToDependencies = {};
+ _dependenciesCount = 0;
+ _needsEvaluation = false;
+ }
+
+ function evaluatePossiblyAsync() {
+ var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
+ if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
+ clearTimeout(evaluationTimeoutInstance);
+ evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
+ } else if (dependentObservable._evalRateLimited) {
+ dependentObservable._evalRateLimited();
+ } else {
+ evaluateImmediate();
+ }
+ }
+
+ function evaluateImmediate() {
+ if (_isBeingEvaluated) {
+ // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
+ // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
+ // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
+ // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
+ return;
+ }
+
+ // Do not evaluate (and possibly capture new dependencies) if disposed
+ if (_isDisposed) {
+ return;
+ }
+
+ if (disposeWhen && disposeWhen()) {
+ // See comment below about _suppressDisposalUntilDisposeWhenReturnsFalse
+ if (!_suppressDisposalUntilDisposeWhenReturnsFalse) {
+ dispose();
+ return;
+ }
+ } else {
+ // It just did return false, so we can stop suppressing now
+ _suppressDisposalUntilDisposeWhenReturnsFalse = false;
+ }
+
+ _isBeingEvaluated = true;
+ try {
+ // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
+ // Then, during evaluation, we cross off any that are in fact still being used.
+ var disposalCandidates = _subscriptionsToDependencies, disposalCount = _dependenciesCount;
+ ko.dependencyDetection.begin({
+ callback: function(subscribable, id) {
+ if (!_isDisposed) {
+ if (disposalCount && disposalCandidates[id]) {
+ // Don't want to dispose this subscription, as it's still being used
+ _subscriptionsToDependencies[id] = disposalCandidates[id];
+ ++_dependenciesCount;
+ delete disposalCandidates[id];
+ --disposalCount;
+ } else {
+ // Brand new subscription - add it
+ addSubscriptionToDependency(subscribable, id);
+ }
+ }
+ },
+ computed: dependentObservable,
+ isInitial: !_dependenciesCount // If we're evaluating when there are no previous dependencies, it must be the first time
+ });
+
+ _subscriptionsToDependencies = {};
+ _dependenciesCount = 0;
+
+ try {
+ var newValue = evaluatorFunctionTarget ? readFunction.call(evaluatorFunctionTarget) : readFunction();
+
+ } finally {
+ ko.dependencyDetection.end();
+
+ // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
+ if (disposalCount) {
+ ko.utils.objectForEach(disposalCandidates, function(id, toDispose) {
+ toDispose.dispose();
+ });
+ }
+
+ _needsEvaluation = false;
+ }
+
+ if (dependentObservable.isDifferent(_latestValue, newValue)) {
+ dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
+
+ _latestValue = newValue;
+ if (DEBUG) dependentObservable._latestValue = _latestValue;
+
+ // If rate-limited, the notification will happen within the limit function. Otherwise,
+ // notify as soon as the value changes. Check specifically for the throttle setting since
+ // it overrides rateLimit.
+ if (!dependentObservable._evalRateLimited || dependentObservable['throttleEvaluation']) {
+ dependentObservable["notifySubscribers"](_latestValue);
+ }
+ }
+ } finally {
+ _isBeingEvaluated = false;
+ }
+
+ if (!_dependenciesCount)
+ dispose();
+ }
+
+ function dependentObservable() {
+ if (arguments.length > 0) {
+ if (typeof writeFunction === "function") {
+ // Writing a value
+ writeFunction.apply(evaluatorFunctionTarget, arguments);
+ } else {
+ throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
+ }
+ return this; // Permits chained assignments
+ } else {
+ // Reading the value
+ if (_needsEvaluation)
+ evaluateImmediate();
+ ko.dependencyDetection.registerDependency(dependentObservable);
+ return _latestValue;
+ }
+ }
+
+ function peek() {
+ // Peek won't re-evaluate, except to get the initial value when "deferEvaluation" is set.
+ // That's the only time that both of these conditions will be satisfied.
+ if (_needsEvaluation && !_dependenciesCount)
+ evaluateImmediate();
+ return _latestValue;
+ }
+
+ function isActive() {
+ return _needsEvaluation || _dependenciesCount > 0;
+ }
+
+ // By here, "options" is always non-null
+ var writeFunction = options["write"],
+ disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
+ disposeWhenOption = options["disposeWhen"] || options.disposeWhen,
+ disposeWhen = disposeWhenOption,
+ dispose = disposeAllSubscriptionsToDependencies,
+ _subscriptionsToDependencies = {},
+ _dependenciesCount = 0,
+ evaluationTimeoutInstance = null;
+
+ if (!evaluatorFunctionTarget)
+ evaluatorFunctionTarget = options["owner"];
+
+ ko.subscribable.call(dependentObservable);
+ ko.utils.setPrototypeOfOrExtend(dependentObservable, ko.dependentObservable['fn']);
+
+ dependentObservable.peek = peek;
+ dependentObservable.getDependenciesCount = function () { return _dependenciesCount; };
+ dependentObservable.hasWriteFunction = typeof options["write"] === "function";
+ dependentObservable.dispose = function () { dispose(); };
+ dependentObservable.isActive = isActive;
+
+ // Replace the limit function with one that delays evaluation as well.
+ var originalLimit = dependentObservable.limit;
+ dependentObservable.limit = function(limitFunction) {
+ originalLimit.call(dependentObservable, limitFunction);
+ dependentObservable._evalRateLimited = function() {
+ dependentObservable._rateLimitedBeforeChange(_latestValue);
+
+ _needsEvaluation = true; // Mark as dirty
+
+ // Pass the observable to the rate-limit code, which will access it when
+ // it's time to do the notification.
+ dependentObservable._rateLimitedChange(dependentObservable);
+ }
+ };
+
+ ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
+ ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
+ ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
+ ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
+
+ // Add a "disposeWhen" callback that, on each evaluation, disposes if the node was removed without using ko.removeNode.
+ if (disposeWhenNodeIsRemoved) {
+ // Since this computed is associated with a DOM node, and we don't want to dispose the computed
+ // until the DOM node is *removed* from the document (as opposed to never having been in the document),
+ // we'll prevent disposal until "disposeWhen" first returns false.
+ _suppressDisposalUntilDisposeWhenReturnsFalse = true;
+
+ // Only watch for the node's disposal if the value really is a node. It might not be,
+ // e.g., { disposeWhenNodeIsRemoved: true } can be used to opt into the "only dispose
+ // after first false result" behaviour even if there's no specific node to watch. This
+ // technique is intended for KO's internal use only and shouldn't be documented or used
+ // by application code, as it's likely to change in a future version of KO.
+ if (disposeWhenNodeIsRemoved.nodeType) {
+ disposeWhen = function () {
+ return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || (disposeWhenOption && disposeWhenOption());
+ };
+ }
+ }
+
+ // Evaluate, unless deferEvaluation is true
+ if (options['deferEvaluation'] !== true)
+ evaluateImmediate();
+
+ // Attach a DOM node disposal callback so that the computed will be proactively disposed as soon as the node is
+ // removed using ko.removeNode. But skip if isActive is false (there will never be any dependencies to dispose).
+ if (disposeWhenNodeIsRemoved && isActive() && disposeWhenNodeIsRemoved.nodeType) {
+ dispose = function() {
+ ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, dispose);
+ disposeAllSubscriptionsToDependencies();
+ };
+ ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
+ }
+
+ return dependentObservable;
+};
+
+ko.isComputed = function(instance) {
+ return ko.hasPrototype(instance, ko.dependentObservable);
+};
+
+var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
+ko.dependentObservable[protoProp] = ko.observable;
+
+ko.dependentObservable['fn'] = {
+ "equalityComparer": valuesArePrimitiveAndEqual
+};
+ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
+
+// Note that for browsers that don't support proto assignment, the
+// inheritance chain is created manually in the ko.dependentObservable constructor
+if (ko.utils.canSetPrototype) {
+ ko.utils.setPrototypeOf(ko.dependentObservable['fn'], ko.subscribable['fn']);
+}
+
+ko.exportSymbol('dependentObservable', ko.dependentObservable);
+ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
+ko.exportSymbol('isComputed', ko.isComputed);
+
+(function() {
+ var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
+
+ ko.toJS = function(rootObject) {
+ if (arguments.length == 0)
+ throw new Error("When calling ko.toJS, pass the object you want to convert.");
+
+ // We just unwrap everything at every level in the object graph
+ return mapJsObjectGraph(rootObject, function(valueToMap) {
+ // Loop because an observable's value might in turn be another observable wrapper
+ for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
+ valueToMap = valueToMap();
+ return valueToMap;
+ });
+ };
+
+ ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
+ var plainJavaScriptObject = ko.toJS(rootObject);
+ return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
+ };
+
+ function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
+ visitedObjects = visitedObjects || new objectLookup();
+
+ rootObject = mapInputCallback(rootObject);
+ var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date)) && (!(rootObject instanceof String)) && (!(rootObject instanceof Number)) && (!(rootObject instanceof Boolean));
+ if (!canHaveProperties)
+ return rootObject;
+
+ var outputProperties = rootObject instanceof Array ? [] : {};
+ visitedObjects.save(rootObject, outputProperties);
+
+ visitPropertiesOrArrayEntries(rootObject, function(indexer) {
+ var propertyValue = mapInputCallback(rootObject[indexer]);
+
+ switch (typeof propertyValue) {
+ case "boolean":
+ case "number":
+ case "string":
+ case "function":
+ outputProperties[indexer] = propertyValue;
+ break;
+ case "object":
+ case "undefined":
+ var previouslyMappedValue = visitedObjects.get(propertyValue);
+ outputProperties[indexer] = (previouslyMappedValue !== undefined)
+ ? previouslyMappedValue
+ : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
+ break;
+ }
+ });
+
+ return outputProperties;
+ }
+
+ function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
+ if (rootObject instanceof Array) {
+ for (var i = 0; i < rootObject.length; i++)
+ visitorCallback(i);
+
+ // For arrays, also respect toJSON property for custom mappings (fixes #278)
+ if (typeof rootObject['toJSON'] == 'function')
+ visitorCallback('toJSON');
+ } else {
+ for (var propertyName in rootObject) {
+ visitorCallback(propertyName);
+ }
+ }
+ };
+
+ function objectLookup() {
+ this.keys = [];
+ this.values = [];
+ };
+
+ objectLookup.prototype = {
+ constructor: objectLookup,
+ save: function(key, value) {
+ var existingIndex = ko.utils.arrayIndexOf(this.keys, key);
+ if (existingIndex >= 0)
+ this.values[existingIndex] = value;
+ else {
+ this.keys.push(key);
+ this.values.push(value);
+ }
+ },
+ get: function(key) {
+ var existingIndex = ko.utils.arrayIndexOf(this.keys, key);
+ return (existingIndex >= 0) ? this.values[existingIndex] : undefined;
+ }
+ };
+})();
+
+ko.exportSymbol('toJS', ko.toJS);
+ko.exportSymbol('toJSON', ko.toJSON);
+(function () {
+ var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
+
+ // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
+ // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
+ // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
+ ko.selectExtensions = {
+ readValue : function(element) {
+ switch (ko.utils.tagNameLower(element)) {
+ case 'option':
+ if (element[hasDomDataExpandoProperty] === true)
+ return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
+ return ko.utils.ieVersion <= 7
+ ? (element.getAttributeNode('value') && element.getAttributeNode('value').specified ? element.value : element.text)
+ : element.value;
+ case 'select':
+ return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
+ default:
+ return element.value;
+ }
+ },
+
+ writeValue: function(element, value, allowUnset) {
+ switch (ko.utils.tagNameLower(element)) {
+ case 'option':
+ switch(typeof value) {
+ case "string":
+ ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
+ if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
+ delete element[hasDomDataExpandoProperty];
+ }
+ element.value = value;
+ break;
+ default:
+ // Store arbitrary object using DomData
+ ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
+ element[hasDomDataExpandoProperty] = true;
+
+ // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
+ element.value = typeof value === "number" ? value : "";
+ break;
+ }
+ break;
+ case 'select':
+ if (value === "" || value === null) // A blank string or null value will select the caption
+ value = undefined;
+ var selection = -1;
+ for (var i = 0, n = element.options.length, optionValue; i < n; ++i) {
+ optionValue = ko.selectExtensions.readValue(element.options[i]);
+ // Include special check to handle selecting a caption with a blank string value
+ if (optionValue == value || (optionValue == "" && value === undefined)) {
+ selection = i;
+ break;
+ }
+ }
+ if (allowUnset || selection >= 0 || (value === undefined && element.size > 1)) {
+ element.selectedIndex = selection;
+ }
+ break;
+ default:
+ if ((value === null) || (value === undefined))
+ value = "";
+ element.value = value;
+ break;
+ }
+ }
+ };
+})();
+
+ko.exportSymbol('selectExtensions', ko.selectExtensions);
+ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
+ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
+ko.expressionRewriting = (function () {
+ var javaScriptReservedWords = ["true", "false", "null", "undefined"];
+
+ // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
+ // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
+ // This also will not properly handle nested brackets (e.g., obj1[obj2['prop']]; see #911).
+ var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
+
+ function getWriteableValue(expression) {
+ if (ko.utils.arrayIndexOf(javaScriptReservedWords, expression) >= 0)
+ return false;
+ var match = expression.match(javaScriptAssignmentTarget);
+ return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
+ }
+
+ // The following regular expressions will be used to split an object-literal string into tokens
+
+ // These two match strings, either with double quotes or single quotes
+ var stringDouble = '"(?:[^"\\\\]|\\\\.)*"',
+ stringSingle = "'(?:[^'\\\\]|\\\\.)*'",
+ // Matches a regular expression (text enclosed by slashes), but will also match sets of divisions
+ // as a regular expression (this is handled by the parsing loop below).
+ stringRegexp = '/(?:[^/\\\\]|\\\\.)*/\w*',
+ // These characters have special meaning to the parser and must not appear in the middle of a
+ // token, except as part of a string.
+ specials = ',"\'{}()/:[\\]',
+ // Match text (at least two characters) that does not contain any of the above special characters,
+ // although some of the special characters are allowed to start it (all but the colon and comma).
+ // The text can contain spaces, but leading or trailing spaces are skipped.
+ everyThingElse = '[^\\s:,/][^' + specials + ']*[^\\s' + specials + ']',
+ // Match any non-space character not matched already. This will match colons and commas, since they're
+ // not matched by "everyThingElse", but will also match any other single character that wasn't already
+ // matched (for example: in "a: 1, b: 2", each of the non-space characters will be matched by oneNotSpace).
+ oneNotSpace = '[^\\s]',
+
+ // Create the actual regular expression by or-ing the above strings. The order is important.
+ bindingToken = RegExp(stringDouble + '|' + stringSingle + '|' + stringRegexp + '|' + everyThingElse + '|' + oneNotSpace, 'g'),
+
+ // Match end of previous token to determine whether a slash is a division or regex.
+ divisionLookBehind = /[\])"'A-Za-z0-9_$]+$/,
+ keywordRegexLookBehind = {'in':1,'return':1,'typeof':1};
+
+ function parseObjectLiteral(objectLiteralString) {
+ // Trim leading and trailing spaces from the string
+ var str = ko.utils.stringTrim(objectLiteralString);
+
+ // Trim braces '{' surrounding the whole object literal
+ if (str.charCodeAt(0) === 123) str = str.slice(1, -1);
+
+ // Split into tokens
+ var result = [], toks = str.match(bindingToken), key, values, depth = 0;
+
+ if (toks) {
+ // Append a comma so that we don't need a separate code block to deal with the last item
+ toks.push(',');
+
+ for (var i = 0, tok; tok = toks[i]; ++i) {
+ var c = tok.charCodeAt(0);
+ // A comma signals the end of a key/value pair if depth is zero
+ if (c === 44) { // ","
+ if (depth <= 0) {
+ if (key)
+ result.push(values ? {key: key, value: values.join('')} : {'unknown': key});
+ key = values = depth = 0;
+ continue;
+ }
+ // Simply skip the colon that separates the name and value
+ } else if (c === 58) { // ":"
+ if (!values)
+ continue;
+ // A set of slashes is initially matched as a regular expression, but could be division
+ } else if (c === 47 && i && tok.length > 1) { // "/"
+ // Look at the end of the previous token to determine if the slash is actually division
+ var match = toks[i-1].match(divisionLookBehind);
+ if (match && !keywordRegexLookBehind[match[0]]) {
+ // The slash is actually a division punctuator; re-parse the remainder of the string (not including the slash)
+ str = str.substr(str.indexOf(tok) + 1);
+ toks = str.match(bindingToken);
+ toks.push(',');
+ i = -1;
+ // Continue with just the slash
+ tok = '/';
+ }
+ // Increment depth for parentheses, braces, and brackets so that interior commas are ignored
+ } else if (c === 40 || c === 123 || c === 91) { // '(', '{', '['
+ ++depth;
+ } else if (c === 41 || c === 125 || c === 93) { // ')', '}', ']'
+ --depth;
+ // The key must be a single token; if it's a string, trim the quotes
+ } else if (!key && !values) {
+ key = (c === 34 || c === 39) /* '"', "'" */ ? tok.slice(1, -1) : tok;
+ continue;
+ }
+ if (values)
+ values.push(tok);
+ else
+ values = [tok];
+ }
+ }
+ return result;
+ }
+
+ // Two-way bindings include a write function that allow the handler to update the value even if it's not an observable.
+ var twoWayBindings = {};
+
+ function preProcessBindings(bindingsStringOrKeyValueArray, bindingOptions) {
+ bindingOptions = bindingOptions || {};
+
+ function processKeyValue(key, val) {
+ var writableVal;
+ function callPreprocessHook(obj) {
+ return (obj && obj['preprocess']) ? (val = obj['preprocess'](val, key, processKeyValue)) : true;
+ }
+ if (!callPreprocessHook(ko['getBindingHandler'](key)))
+ return;
+
+ if (twoWayBindings[key] && (writableVal = getWriteableValue(val))) {
+ // For two-way bindings, provide a write method in case the value
+ // isn't a writable observable.
+ propertyAccessorResultStrings.push("'" + key + "':function(_z){" + writableVal + "=_z}");
+ }
+
+ // Values are wrapped in a function so that each value can be accessed independently
+ if (makeValueAccessors) {
+ val = 'function(){return ' + val + ' }';
+ }
+ resultStrings.push("'" + key + "':" + val);
+ }
+
+ var resultStrings = [],
+ propertyAccessorResultStrings = [],
+ makeValueAccessors = bindingOptions['valueAccessors'],
+ keyValueArray = typeof bindingsStringOrKeyValueArray === "string" ?
+ parseObjectLiteral(bindingsStringOrKeyValueArray) : bindingsStringOrKeyValueArray;
+
+ ko.utils.arrayForEach(keyValueArray, function(keyValue) {
+ processKeyValue(keyValue.key || keyValue['unknown'], keyValue.value);
+ });
+
+ if (propertyAccessorResultStrings.length)
+ processKeyValue('_ko_property_writers', "{" + propertyAccessorResultStrings.join(",") + " }");
+
+ return resultStrings.join(",");
+ }
+
+ return {
+ bindingRewriteValidators: [],
+
+ twoWayBindings: twoWayBindings,
+
+ parseObjectLiteral: parseObjectLiteral,
+
+ preProcessBindings: preProcessBindings,
+
+ keyValueArrayContainsKey: function(keyValueArray, key) {
+ for (var i = 0; i < keyValueArray.length; i++)
+ if (keyValueArray[i]['key'] == key)
+ return true;
+ return false;
+ },
+
+ // Internal, private KO utility for updating model properties from within bindings
+ // property: If the property being updated is (or might be) an observable, pass it here
+ // If it turns out to be a writable observable, it will be written to directly
+ // allBindings: An object with a get method to retrieve bindings in the current execution context.
+ // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
+ // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
+ // value: The value to be written
+ // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
+ // it is !== existing value on that writable observable
+ writeValueToProperty: function(property, allBindings, key, value, checkIfDifferent) {
+ if (!property || !ko.isObservable(property)) {
+ var propWriters = allBindings.get('_ko_property_writers');
+ if (propWriters && propWriters[key])
+ propWriters[key](value);
+ } else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) {
+ property(value);
+ }
+ }
+ };
+})();
+
+ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
+ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
+ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
+ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
+
+// Making bindings explicitly declare themselves as "two way" isn't ideal in the long term (it would be better if
+// all bindings could use an official 'property writer' API without needing to declare that they might). However,
+// since this is not, and has never been, a public API (_ko_property_writers was never documented), it's acceptable
+// as an internal implementation detail in the short term.
+// For those developers who rely on _ko_property_writers in their custom bindings, we expose _twoWayBindings as an
+// undocumented feature that makes it relatively easy to upgrade to KO 3.0. However, this is still not an official
+// public API, and we reserve the right to remove it at any time if we create a real public property writers API.
+ko.exportSymbol('expressionRewriting._twoWayBindings', ko.expressionRewriting.twoWayBindings);
+
+// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
+// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
+ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
+ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);
+(function() {
+ // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
+ // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
+ // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
+ // of that virtual hierarchy
+ //
+ // The point of all this is to support containerless templates (e.g., blah)
+ // without having to scatter special cases all over the binding and templating code.
+
+ // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
+ // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
+ // So, use node.text where available, and node.nodeValue elsewhere
+ var commentNodesHaveTextProperty = document && document.createComment("test").text === "";
+
+ var startCommentRegex = commentNodesHaveTextProperty ? /^$/ : /^\s*ko(?:\s+([\s\S]+))?\s*$/;
+ var endCommentRegex = commentNodesHaveTextProperty ? /^$/ : /^\s*\/ko\s*$/;
+ var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
+
+ function isStartComment(node) {
+ return (node.nodeType == 8) && startCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);
+ }
+
+ function isEndComment(node) {
+ return (node.nodeType == 8) && endCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);
+ }
+
+ function getVirtualChildren(startComment, allowUnbalanced) {
+ var currentNode = startComment;
+ var depth = 1;
+ var children = [];
+ while (currentNode = currentNode.nextSibling) {
+ if (isEndComment(currentNode)) {
+ depth--;
+ if (depth === 0)
+ return children;
+ }
+
+ children.push(currentNode);
+
+ if (isStartComment(currentNode))
+ depth++;
+ }
+ if (!allowUnbalanced)
+ throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
+ return null;
+ }
+
+ function getMatchingEndComment(startComment, allowUnbalanced) {
+ var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
+ if (allVirtualChildren) {
+ if (allVirtualChildren.length > 0)
+ return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
+ return startComment.nextSibling;
+ } else
+ return null; // Must have no matching end comment, and allowUnbalanced is true
+ }
+
+ function getUnbalancedChildTags(node) {
+ // e.g., from
OK
Another, returns: Another
+ // from
OK
, returns:
+ var childNode = node.firstChild, captureRemaining = null;
+ if (childNode) {
+ do {
+ if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
+ captureRemaining.push(childNode);
+ else if (isStartComment(childNode)) {
+ var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
+ if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
+ childNode = matchingEndComment;
+ else
+ captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
+ } else if (isEndComment(childNode)) {
+ captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
+ }
+ } while (childNode = childNode.nextSibling);
+ }
+ return captureRemaining;
+ }
+
+ ko.virtualElements = {
+ allowedBindings: {},
+
+ childNodes: function(node) {
+ return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
+ },
+
+ emptyNode: function(node) {
+ if (!isStartComment(node))
+ ko.utils.emptyDomNode(node);
+ else {
+ var virtualChildren = ko.virtualElements.childNodes(node);
+ for (var i = 0, j = virtualChildren.length; i < j; i++)
+ ko.removeNode(virtualChildren[i]);
+ }
+ },
+
+ setDomNodeChildren: function(node, childNodes) {
+ if (!isStartComment(node))
+ ko.utils.setDomNodeChildren(node, childNodes);
+ else {
+ ko.virtualElements.emptyNode(node);
+ var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
+ for (var i = 0, j = childNodes.length; i < j; i++)
+ endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
+ }
+ },
+
+ prepend: function(containerNode, nodeToPrepend) {
+ if (!isStartComment(containerNode)) {
+ if (containerNode.firstChild)
+ containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
+ else
+ containerNode.appendChild(nodeToPrepend);
+ } else {
+ // Start comments must always have a parent and at least one following sibling (the end comment)
+ containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
+ }
+ },
+
+ insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
+ if (!insertAfterNode) {
+ ko.virtualElements.prepend(containerNode, nodeToInsert);
+ } else if (!isStartComment(containerNode)) {
+ // Insert after insertion point
+ if (insertAfterNode.nextSibling)
+ containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
+ else
+ containerNode.appendChild(nodeToInsert);
+ } else {
+ // Children of start comments must always have a parent and at least one following sibling (the end comment)
+ containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
+ }
+ },
+
+ firstChild: function(node) {
+ if (!isStartComment(node))
+ return node.firstChild;
+ if (!node.nextSibling || isEndComment(node.nextSibling))
+ return null;
+ return node.nextSibling;
+ },
+
+ nextSibling: function(node) {
+ if (isStartComment(node))
+ node = getMatchingEndComment(node);
+ if (node.nextSibling && isEndComment(node.nextSibling))
+ return null;
+ return node.nextSibling;
+ },
+
+ hasBindingValue: isStartComment,
+
+ virtualNodeBindingValue: function(node) {
+ var regexMatch = (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
+ return regexMatch ? regexMatch[1] : null;
+ },
+
+ normaliseVirtualElementDomStructure: function(elementVerified) {
+ // Workaround for https://github.com/SteveSanderson/knockout/issues/155
+ // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing tags as if they don't exist, thereby moving comment nodes
+ // that are direct descendants of
into the preceding
)
+ if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
+ return;
+
+ // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
+ // must be intended to appear *after* that child, so move them there.
+ var childNode = elementVerified.firstChild;
+ if (childNode) {
+ do {
+ if (childNode.nodeType === 1) {
+ var unbalancedTags = getUnbalancedChildTags(childNode);
+ if (unbalancedTags) {
+ // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
+ var nodeToInsertBefore = childNode.nextSibling;
+ for (var i = 0; i < unbalancedTags.length; i++) {
+ if (nodeToInsertBefore)
+ elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
+ else
+ elementVerified.appendChild(unbalancedTags[i]);
+ }
+ }
+ }
+ } while (childNode = childNode.nextSibling);
+ }
+ }
+ };
+})();
+ko.exportSymbol('virtualElements', ko.virtualElements);
+ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
+ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
+//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
+ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
+//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
+ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
+ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
+(function() {
+ var defaultBindingAttributeName = "data-bind";
+
+ ko.bindingProvider = function() {
+ this.bindingCache = {};
+ };
+
+ ko.utils.extend(ko.bindingProvider.prototype, {
+ 'nodeHasBindings': function(node) {
+ switch (node.nodeType) {
+ case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
+ case 8: return ko.virtualElements.hasBindingValue(node); // Comment node
+ default: return false;
+ }
+ },
+
+ 'getBindings': function(node, bindingContext) {
+ var bindingsString = this['getBindingsString'](node, bindingContext);
+ return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
+ },
+
+ 'getBindingAccessors': function(node, bindingContext) {
+ var bindingsString = this['getBindingsString'](node, bindingContext);
+ return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node, {'valueAccessors':true}) : null;
+ },
+
+ // The following function is only used internally by this default provider.
+ // It's not part of the interface definition for a general binding provider.
+ 'getBindingsString': function(node, bindingContext) {
+ switch (node.nodeType) {
+ case 1: return node.getAttribute(defaultBindingAttributeName); // Element
+ case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
+ default: return null;
+ }
+ },
+
+ // The following function is only used internally by this default provider.
+ // It's not part of the interface definition for a general binding provider.
+ 'parseBindingsString': function(bindingsString, bindingContext, node, options) {
+ try {
+ var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache, options);
+ return bindingFunction(bindingContext, node);
+ } catch (ex) {
+ ex.message = "Unable to parse bindings.\nBindings value: " + bindingsString + "\nMessage: " + ex.message;
+ throw ex;
+ }
+ }
+ });
+
+ ko.bindingProvider['instance'] = new ko.bindingProvider();
+
+ function createBindingsStringEvaluatorViaCache(bindingsString, cache, options) {
+ var cacheKey = bindingsString + (options && options['valueAccessors'] || '');
+ return cache[cacheKey]
+ || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString, options));
+ }
+
+ function createBindingsStringEvaluator(bindingsString, options) {
+ // Build the source for a function that evaluates "expression"
+ // For each scope variable, add an extra level of "with" nesting
+ // Example result: with(sc1) { with(sc0) { return (expression) } }
+ var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),
+ functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
+ return new Function("$context", "$element", functionBody);
+ }
+})();
+
+ko.exportSymbol('bindingProvider', ko.bindingProvider);
+(function () {
+ ko.bindingHandlers = {};
+
+ // The following element types will not be recursed into during binding. In the future, we
+ // may consider adding to this list, because such elements' contents are always
+ // intended to be bound in a different context from where they appear in the document.
+ var bindingDoesNotRecurseIntoElementTypes = {
+ // Don't want bindings that operate on text nodes to mutate
+ ';
+
+ }
+
+
+
+ public static function cookie_baker() {
+
+ /* If headers were already sent, then don't follow through with this function or it will err. */
+ if ( headers_sent() )
+ return false;
+
+ if ( headway_get('full-site') == 'true' )
+ return setcookie('headway-full-site', 1, time() + 60 * 60 * 24 * 7, '/');
+
+ if ( headway_get('full-site') == 'false' )
+ return setcookie('headway-full-site', false, time() - 3600, '/');
+
+ return false;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/common/route.php b/wp-content/themes/headway/library/common/route.php
new file mode 100644
index 0000000..21d65b6
--- /dev/null
+++ b/wp-content/themes/headway/library/common/route.php
@@ -0,0 +1,239 @@
+ Return to Home');
+
+ return false;
+
+ //If the user isn't logged in at all, log 'em in and loop back to visual editor as long as debug mode isn't active
+ } elseif ( !is_user_logged_in() && !HeadwayOption::get('debug-mode') ) {
+
+ return auth_redirect();
+
+ } else if ( defined('FORCE_SSL_ADMIN') && FORCE_SSL_ADMIN && !is_ssl() ) {
+
+ wp_safe_redirect(str_replace('http://', 'https://', headway_get_current_url()));
+ die();
+
+ }
+
+ HeadwayVisualEditor::display();
+ die();
+
+ //Theme Preview
+ } elseif ( self::is_grid() ) {
+
+ Headway::load('visual-editor/iframe-grid');
+
+ HeadwayVisualEditorIframeGrid::show();
+ die();
+
+ }
+
+ }
+
+
+ public static function maybe_run_trigger() {
+
+ if ( !self::is_trigger() )
+ return;
+
+ add_filter('restricted_site_access_is_restricted', '__return_false');
+
+ //Deactivate redirect so the weird 301's don't happen
+ remove_action('template_redirect', 'redirect_canonical');
+ add_filter('wp_redirect', '__return_false', 12);
+
+ //Cycle through
+ switch ( headway_get('headway-trigger') ) {
+
+ case 'compiler':
+ HeadwayCompiler::output_trigger();
+ break;
+
+ case 'layout-redirect':
+ self::redirect_to_layout();
+ break;
+
+ case 'media-uploader':
+ if ( !HeadwayCapabilities::can_user_visually_edit() )
+ die();
+
+ Headway::load('visual-editor/media-uploader');
+ break;
+
+ case 'ace-editor':
+ if ( !HeadwayCapabilities::can_user_visually_edit() )
+ die();
+
+ Headway::load('visual-editor/ace-editor');
+ break;
+
+ }
+
+ exit;
+
+ }
+
+
+ /**
+ * If a post, page, or any other singular item has the 301 Redirect set, then do the redirect.
+ **/
+ public static function maybe_redirect_301() {
+
+ global $post;
+
+ //Don't try redirecting if the headers are already sent. Otherwise, it'll result in an error and no redirect.
+ if ( headers_sent() )
+ return false;
+
+ //Make sure that it's a single post and that $post is a valid object.
+ if ( !is_object($post) || !is_singular() )
+ return false;
+
+ //Do not try redirecting if it's the visual editor or admin
+ if ( is_admin() || self::is_visual_editor() || self::is_visual_editor_iframe() )
+ return false;
+
+ //If the redirect URL isn't set, then don't try anything.
+ if ( !($redirect_url = HeadwayLayoutOption::get($post->ID, 'redirect-301', null, true, 'seo')) )
+ return false;
+
+ //If there is no HTTP or HTTPS in the URL, add it.
+ if ( strpos($redirect_url, 'http://') !== 0 && strpos($redirect_url, 'https://') !== 0 )
+ $redirect_url = 'http://' . $redirect_url;
+
+ wp_redirect($redirect_url, 301);
+ die();
+
+ }
+
+
+ /**
+ * Determine whether or not the site is being viewed in normal display mode.
+ *
+ * @return bool
+ **/
+ public static function is_display() {
+
+ if ( self::is_visual_editor() )
+ return false;
+
+ if ( self::is_trigger() )
+ return false;
+
+ if ( is_admin() )
+ return false;
+
+ return true;
+
+ }
+
+
+ /**
+ * Checks if the visual editor is open.
+ *
+ * @return bool
+ **/
+ public static function is_visual_editor() {
+
+ return headway_get('visual-editor', false);
+
+ }
+
+
+ public static function is_trigger() {
+
+ return ( headway_get('headway-trigger') ) ? true : false;
+
+ }
+
+
+ public static function is_theme_preview() {
+
+ return (headway_get('preview') == 1 && headway_get('preview_iframe') == 1) || headway_post('wp_customize');
+
+ }
+
+
+ public static function is_visual_editor_iframe($mode = null) {
+
+ if ( !headway_get('ve-iframe') || !HeadwayCapabilities::can_user_visually_edit() )
+ return false;
+
+ if ( $mode )
+ return headway_get('ve-iframe-mode') == $mode;
+
+ return true;
+
+ }
+
+
+ public static function is_grid() {
+
+ return self::is_visual_editor_iframe('grid');
+
+ }
+
+
+ /**
+ * Used for when a user clicks View Site in the Visual Editor
+ **/
+ public static function redirect_to_layout() {
+
+ remove_filter('wp_redirect', '__return_false', 12);
+
+ if ( headway_get('debug') && HeadwayCapabilities::can_user_visually_edit() )
+ wp_die(HeadwayLayout::get_url(headway_get('layout')));
+
+ return wp_safe_redirect(HeadwayLayout::get_url(headway_get('layout')));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/common/seo.php b/wp-content/themes/headway/library/common/seo.php
new file mode 100644
index 0000000..21da48c
--- /dev/null
+++ b/wp-content/themes/headway/library/common/seo.php
@@ -0,0 +1,352 @@
+';
+
+ elseif ( headway_get('description', $seo_templates) )
+ $meta .= "\n" . '';
+
+ //Robots
+ $robot_settings = array();
+
+ if ( self::is_seo_checkbox_enabled('noindex') )
+ $robot_settings[] = 'noindex';
+
+ if ( self::is_seo_checkbox_enabled('noarchive') )
+ $robot_settings[] = 'noarchive';
+
+ if ( self::is_seo_checkbox_enabled('nosnippet') )
+ $robot_settings[] = 'nosnippet';
+
+ if ( self::is_seo_checkbox_enabled('noodp') )
+ $robot_settings[] = 'noodp';
+
+ if ( self::is_seo_checkbox_enabled('noydir') )
+ $robot_settings[] = 'noydir';
+
+ if ( count($robot_settings) !== 0 )
+ $meta .= "\n" . '';
+
+ if ( strlen($meta) !== 0 )
+ echo "\n\n" . '' . $meta . "\n";
+
+ do_action('headway_seo_meta');
+
+ }
+
+
+ public static function is_seo_checkbox_enabled($option, $layout = false) {
+
+ if ( !$layout )
+ $layout = HeadwayLayout::get_current();
+
+ $seo_templates = self::get_seo_templates(self::current_seo_layout());
+
+ if ( HeadwayLayoutOption::get($layout, $option, null, true, 'seo') === null && !headway_get($option, $seo_templates) )
+ return false;
+
+ if ( HeadwayLayoutOption::get($layout, $option, null, true, 'seo') === false )
+ return false;
+
+ return true;
+
+ }
+
+
+ /**
+ * Filter that removes nofollow from the comment author URLs.
+ *
+ * @param string $url URL to be filtered.
+ *
+ * @return string $url URL after being filtered.
+ **/
+ public static function comment_rel_nofollow($url) {
+
+ if ( HeadwayOption::get('nofollow-comment-author-url') )
+ return $url;
+
+ return str_replace("rel='external nofollow'", "rel='external'", $url);
+
+ }
+
+
+ public static function current_seo_layout() {
+
+ /* Since the SEO templates are only at a certain level, checking the real layout against the SEO templates would not work. */
+
+ $layout_hierarchy = HeadwayLayout::get_current_hierarchy();
+
+ if ( count($layout_hierarchy) === 1 )
+ return $layout_hierarchy[0];
+ elseif ( count($layout_hierarchy) > 1 )
+ return $layout_hierarchy[1];
+
+ return null;
+
+ }
+
+
+ public static function parse_seo_variables($content) {
+
+ $tagline = get_option('blogdescription');
+ $sitename = get_option('blogname');
+
+ $queried_object = get_queried_object();
+
+ //Figure out the title variable
+ if ( is_front_page() || ( is_home() && get_option('show_on_front') != 'page' ) )
+ $title = 'Home';
+
+ elseif ( is_home() && get_option('show_on_front') == 'page' )
+ $title = 'Blog';
+
+ elseif ( is_singular() )
+ $title = get_the_title();
+
+ elseif ( is_archive() ) {
+
+ if ( is_category() ) {
+
+ $title = single_cat_title('', false);
+
+ } elseif ( is_date() ) {
+
+ if ( is_day() )
+ $title = get_the_time(get_option('date_format'));
+ elseif ( is_month() )
+ $title = get_the_time('F Y');
+ elseif ( is_year() )
+ $title = get_the_time('Y');
+
+ } elseif ( is_author() ) {
+
+ $author = get_queried_object();
+ $title = $author->display_name;
+
+ } elseif ( is_tag() ) {
+
+ $title = single_tag_title('', false);
+
+ } elseif ( is_tax() ) {
+
+ $taxonomy = get_taxonomy($queried_object->taxonomy);
+ $term = get_term($queried_object->term_id, $queried_object->taxonomy);
+
+ $title = $taxonomy->labels->singular_name;
+ $meta = $term->name;
+
+ } elseif ( is_post_type_archive() ) {
+
+ $post_type = get_post_type_object($queried_object->name);
+
+ $title = $post_type->labels->name;
+
+ }
+
+ } elseif ( is_search() )
+ $title = get_search_query();
+
+ elseif ( is_404() )
+ $title = '404';
+
+ elseif ( is_feed() )
+ $title = 'Feed';
+
+
+ if ( isset($title) ) {
+
+ $search = array(
+ '%title%',
+ '%category%',
+ '%archive%',
+ '%search%',
+ '%author%',
+ '%tag%',
+ '%post_type_plural%',
+ '%taxonomy%'
+ );
+
+ //Replace title variables
+ $content = str_ireplace($search, $title, $content);
+
+ }
+
+ if ( isset($meta) ) {
+
+ $search = array(
+ '%meta%'
+ );
+
+ $content = str_ireplace($search, $meta, $content);
+
+ }
+
+ $content = str_ireplace('%sitename%', $sitename, $content);
+ $content = str_ireplace('%tagline%', $tagline, $content);
+
+ return esc_attr(stripslashes(strip_tags($content)));
+
+ }
+
+
+ public static function get_seo_templates($layout = false) {
+
+ $seo_templates_query = HeadwayOption::get('seo-templates', 'general', self::output_layouts_and_defaults());
+
+ if ( $layout )
+ return headway_get(self::current_seo_layout(), $seo_templates_query, array());
+ else
+ return $seo_templates_query;
+
+ }
+
+
+ public static function output_layouts_and_defaults() {
+
+ if ( get_option('show_on_front') == 'page' ) {
+
+ $pages = array(
+ 'front_page' => array(
+ 'title' => '%tagline% | %sitename%'
+ ),
+ 'index' => array(
+ 'title' => '%tagline% | %sitename%'
+ ),
+ );
+
+ } else {
+
+ $pages = array(
+ 'index' => array(
+ 'title' => '%tagline% | %sitename%'
+ )
+ );
+
+ }
+
+ //Custom Post Types
+ $excluded_post_type_archives = array('post', 'page', 'attachment');
+ $post_types = get_post_types(array('public' => true), 'objects');
+
+ foreach($post_types as $post_type) {
+ $pages['single-' . $post_type->name] = array(
+ 'title' => '%title% | %sitename%'
+ );
+
+ //If excluded post type archive, skip it
+ if ( !in_array($post_type->name, $excluded_post_type_archives) )
+ $pages['archive-post_type-' . $post_type->name] = array(
+ 'title' => '%post_type_plural% | %sitename%'
+ );
+ }
+
+ //Archives
+ $pages = array_merge($pages, array(
+ 'archive-category' => array(
+ 'title' => '%title% | %sitename%'
+ ),
+ 'archive-search' => array(
+ 'title' => 'Search: %title% | %sitename%',
+ 'noarchive' => true
+ ),
+ 'archive-date' => array(
+ 'title' => '%title% | %sitename%'
+ ),
+ 'archive-author' => array(
+ 'title' => '%title% | %sitename%'
+ ),
+ 'archive-post_tag' => array(
+ 'title' => 'Tag: %title% | %sitename%'
+ ),
+ 'archive-taxonomy' => array(
+ 'title' => '%title%: %meta% | %sitename%'
+ ),
+ 'archive-post_type' => array(
+ 'title' => '%post_type_plural% | %sitename%'
+ ),
+ 'four04' => array(
+ 'title' => 'Whoops! Page Not Found | %sitename%'
+ )
+ ));
+
+ return $pages;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/common/social-optimization.php b/wp-content/themes/headway/library/common/social-optimization.php
new file mode 100644
index 0000000..4065e53
--- /dev/null
+++ b/wp-content/themes/headway/library/common/social-optimization.php
@@ -0,0 +1,36 @@
+ 'base',
+ 'name' => 'Base',
+ 'author' => 'Headway Themes',
+ 'version' => HEADWAY_VERSION,
+ 'image-url' => headway_url() . '/screenshot.png',
+ 'description' => null
+ )
+ );
+
+ $installed_skins = HeadwayOption::get_group('skins');
+
+ if ( !$installed_skins ) {
+ $installed_skins = array();
+ }
+
+ if ( !empty($installed_skins) && is_array($installed_skins) ) {
+
+ foreach ( $installed_skins as $installed_skin_id => $installed_skin ) {
+
+ $skin = array_merge(array(
+ 'id' => $installed_skin_id,
+ 'description' => null,
+ 'version' => null,
+ 'author' => null
+ ), $installed_skin);
+
+ if ( $info_only ) {
+
+ foreach ( $skin as $skin_key => $skin_value ) {
+
+ $keys_allowed = array(
+ 'id',
+ 'name',
+ 'author',
+ 'version',
+ 'image-url',
+ 'description'
+ );
+
+ if ( !in_array($skin_key, $keys_allowed) ) {
+ unset($skin[$skin_key]);
+ }
+
+ }
+
+ }
+
+ $skins[] = $skin;
+
+ }
+
+ }
+
+ /* Resize all images */
+ foreach ( $skins as $skin_index => $skin ) {
+
+ $skins[$skin_index]['image-url'] = headway_resize_image(headway_get('image-url', $skin), 220, 190);
+
+ if ( !$skins[$skin_index]['image-url'] || is_wp_error($skins[$skin_index]['image-url']) )
+ $skins[$skin_index]['image-url'] = headway_get('image-url', $skin);
+
+ }
+
+
+ if ( $associative ) {
+
+ $associative_skins = array();
+
+ foreach ( $skins as $skin )
+ $associative_skins[$skin['id']] = $skin;
+
+ return $associative_skins;
+
+ }
+
+ return $skins;
+
+ }
+
+
+ public static function get_active() {
+
+ $current_skin_id = HeadwayOption::get('current-skin', 'general', HEADWAY_DEFAULT_SKIN);
+ $all_skins = self::get_all(true);
+
+ return headway_get($current_skin_id, $all_skins, headway_get(HEADWAY_DEFAULT_SKIN, $all_skins));
+
+ }
+
+
+ public static function get_active_id() {
+
+ $active_skin = self::get_active();
+
+ return $active_skin['id'];
+
+ }
+
+
+ public static function add() {
+
+
+
+ }
+
+
+ public static function delete() {
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/compatibility/woocommerce/compatibility-woocommerce.php b/wp-content/themes/headway/library/compatibility/woocommerce/compatibility-woocommerce.php
new file mode 100644
index 0000000..9fc2d39
--- /dev/null
+++ b/wp-content/themes/headway/library/compatibility/woocommerce/compatibility-woocommerce.php
@@ -0,0 +1,62 @@
+parent;
+
+ while ( $parent ) {
+
+ $parents[] = $parent;
+
+ $new_parent = get_term_by('id', $parent, get_query_var('taxonomy'));
+ $parent = $new_parent->parent;
+
+ }
+
+ /* Output parent categories */
+ if ( !empty($parents) ) {
+
+ $parents = array_reverse($parents);
+
+ foreach ( $parents as $parent ) {
+
+ $item = get_term_by('id', $parent, get_query_var('taxonomy'));
+
+ $breadcrumbs[get_term_link($item->slug, 'product_cat')] = $item->name;
+
+ }
+
+ }
+
+ /* Add current category */
+ $breadcrumbs[] = single_term_title('', false);
+
+ }
+
+ /* Shop Tags */
+ if ( is_tax('product_tag') ) {
+
+ $breadcrumbs[] = __('Products tagged “', 'hw_sf_wooc') . single_term_title('', false) . _x('”', 'endquote', 'hw_sf_wooc');
+
+ }
+ /* End Shop Taxonomy Archives */
+
+ /* Single Product */
+ if ( is_singular('product') ) {
+
+ /* Remove the current title at end of breadcrumbs. This is easier than trying to put the following items before this item being removed */
+ array_pop($breadcrumbs);
+
+ global $post;
+
+ /* Shop prefix */
+ $shop_url = get_option('woocommerce_prepend_shop_page_to_products');
+ $shop_page_id = woocommerce_get_page_id('shop');
+ $shop_title = get_the_title($shop_page_id);
+
+ if ( 'yes' == $shop_url && $shop_page_id && get_option('page_on_front') !== $shop_page_id )
+ $breadcrumbs[get_permalink($shop_page_id)] = $shop_title;
+
+ /* Product categories */
+ if ( $terms = wp_get_object_terms($post->ID, 'product_cat') ) {
+
+ $term = current($terms);
+ $parents = array();
+ $parent = $term->parent;
+
+ /* Get parent categories */
+ while ( $parent ) {
+
+ $parents[] = $parent;
+
+ $new_parent = get_term_by('id', $parent, 'product_cat');
+ $parent = $new_parent->parent;
+
+ }
+
+ /* Output parent categories */
+ if ( !empty($parents) ) {
+
+ $parents = array_reverse($parents);
+
+ foreach ( $parents as $parent ) {
+
+ $item = get_term_by('id', $parent, 'product_cat');
+ $breadcrumb[get_term_link($item->slug, 'product_cat')] = $item->name;
+
+ }
+
+ }
+
+ /* Output main category */
+ $breadcrumbs[get_term_link($term->slug, 'product_cat')] = $term->name;
+
+ }
+
+ /* Current product */
+ $breadcrumbs[] = get_the_title();
+
+ }
+ /* End Single Product */
+
+ return $breadcrumbs;
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/compatibility/woocommerce/woocommerce-design-defaults.php b/wp-content/themes/headway/library/compatibility/woocommerce/woocommerce-design-defaults.php
new file mode 100644
index 0000000..bda2e90
--- /dev/null
+++ b/wp-content/themes/headway/library/compatibility/woocommerce/woocommerce-design-defaults.php
@@ -0,0 +1,33 @@
+ array(
+ 'properties' => array(
+ 'margin-top' => '10'
+ )
+ ),
+
+ 'block-content-wc-page-title' => array(
+ 'properties' => array(
+ 'font-size' => '24',
+ 'line-height' => '160'
+ )
+ ),
+
+ 'block-content-wc-product-page-short-description' => array(
+ 'properties' => array(
+ 'line-height' => '130'
+ )
+ ),
+
+ 'block-content-wc-related-products-heading' => array(
+ 'properties' => array(
+ 'font-size' => '20',
+ 'line-height' => '150',
+ 'margin-bottom' => '10'
+ )
+ )
+ ));
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/compatibility/woocommerce/woocommerce-design-elements.php b/wp-content/themes/headway/library/compatibility/woocommerce/woocommerce-design-elements.php
new file mode 100644
index 0000000..a831e8d
--- /dev/null
+++ b/wp-content/themes/headway/library/compatibility/woocommerce/woocommerce-design-elements.php
@@ -0,0 +1,136 @@
+ 'blocks',
+ 'id' => 'block-content-wc-page-title',
+ 'parent' => 'block-content',
+ 'name' => 'Shop Title',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content h1.page-title'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-breadcrumbs',
+ 'parent' => 'block-content',
+ 'name' => 'Breadcrumbs',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content .woocommerce-breadcrumb'
+ ));
+
+
+ /* Product Listings */
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-listings-product-containers',
+ 'parent' => 'block-content',
+ 'name' => 'Product Listings',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content ul.products li.product'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-listings-product-names',
+ 'parent' => 'block-content-wc-listings-product-containers',
+ 'name' => 'Product Listings: Names',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content ul.products li.product h3'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-listings-product-images',
+ 'parent' => 'block-content-wc-listings-product-containers',
+ 'name' => 'Product Listings: Images',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content ul.products li.product img'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-listings-product-prices',
+ 'parent' => 'block-content-wc-listings-product-containers',
+ 'name' => 'Product Listings: Prices',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content ul.products li.product span.amount'
+ ));
+ /* End Product Listings */
+
+
+ /* Product Pages */
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-product-page-name',
+ 'parent' => 'block-content',
+ 'name' => 'Product Page: Name',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.product div.summary h1.product_title'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-product-page-image',
+ 'parent' => 'block-content',
+ 'name' => 'Product Page: Image',
+ 'indent-in-selector' => true,
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.product div.images img'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-product-page-price',
+ 'parent' => 'block-content',
+ 'name' => 'Product Page: Price',
+ 'indent-in-selector' => true,
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.product div.summary p.price'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-product-page-short-description',
+ 'parent' => 'block-content',
+ 'name' => 'Product Page: Short Description',
+ 'indent-in-selector' => true,
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.product div.summary div[itemprop="description"]'
+ ));
+ /* End Product Pages */
+
+
+ /* Related Products */
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-related-products',
+ 'parent' => 'block-content',
+ 'name' => 'Related Products Container',
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.related'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-related-products-heading',
+ 'parent' => 'block-content',
+ 'name' => 'Related Products Heading',
+ 'indent-in-selector' => true,
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.related h2'
+ ));
+
+ HeadwayElementAPI::register_element(array(
+ 'group' => 'blocks',
+ 'id' => 'block-content-wc-related-products-product',
+ 'parent' => 'block-content',
+ 'name' => 'Related Product Container',
+ 'indent-in-selector' => true,
+ 'description' => 'Storefront: WooCommerce',
+ 'selector' => '.woocommerce .block-type-content div.related li.product'
+ ));
+ /* End Related Products */
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-blocks.php b/wp-content/themes/headway/library/data/data-blocks.php
new file mode 100644
index 0000000..cb11a81
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-blocks.php
@@ -0,0 +1,641 @@
+ uniqid('b' . strtolower(substr($random_prefix, 0, 2))),
+ 'template' => headway_get('template', $args, HeadwayOption::$current_skin),
+ 'layout' => $layout_id,
+ 'type' => $args['type'],
+ 'wrapper_id' => headway_get('wrapper', $args),
+ 'position' => headway_maybe_serialize($args['position']),
+ 'dimensions' => headway_maybe_serialize($args['dimensions']),
+ 'settings' => headway_maybe_serialize(headway_get('settings', $args, array())),
+ 'mirror_id' => $mirror_id
+ );
+
+ //Is a pre-defined ID required?
+ if ( $insert_id = headway_get( 'insert_id', $args ) )
+ $insert_args['id'] = $insert_id;
+
+ if ( $legacy_id = headway_get( 'legacy_id', $args ) )
+ $insert_args['legacy_id'] = $legacy_id;
+
+ //Run the query
+ $wpdb->insert($wpdb->hw_blocks, $insert_args);
+
+ //All done. Spit back ID of newly created block.
+ return $insert_args['id'];
+
+ }
+
+
+ public static function update_block($block_id, $args) {
+
+ global $wpdb;
+
+ $block_to_be_updated = self::get_block($block_id);
+
+ /* Make sure block exists */
+ if ( !$block_to_be_updated )
+ return null;
+
+ /* Map old args */
+ if ( isset($args['wrapper']) ) {
+
+ $args['wrapper_id'] = $args['wrapper'];
+ unset($args['wrapper']);
+
+ }
+
+ /* Map mirror-block setting to mirror_id column */
+ if ( isset($args['settings']) && isset($args['settings']['mirror-block']) ) {
+
+ $args['mirror_id'] = $args['settings']['mirror-block'];
+ unset($args['settings']['mirror-block']);
+
+ }
+
+ /* Handle template argument */
+ $template = headway_get('template', $args, HeadwayOption::$current_skin);
+
+ if ( isset($args['template']) )
+ unset($args['template']);
+
+ /* Query */
+ $query = $wpdb->update($wpdb->hw_blocks, array_map('headway_maybe_serialize', $args), array(
+ 'template' => $template,
+ 'id' => $block_id
+ ));
+
+ return $query;
+
+ }
+
+
+ public static function delete_block($block_id) {
+
+ global $wpdb;
+
+ $block_to_be_deleted = self::get_block($block_id);
+
+ /* Make sure block exists */
+ if ( !$block_to_be_deleted )
+ return null;
+
+ /* Query for deletion */
+ $query = $wpdb->delete( $wpdb->hw_blocks, array(
+ 'template' => HeadwayOption::$current_skin,
+ 'id' => $block_id
+ ));
+
+ /* Unmirror the blocks mirroring this block */
+ $wpdb->update( $wpdb->hw_blocks, array(
+ 'mirror_id' => ''
+ ), array(
+ 'mirror_id' => $block_id
+ ));
+
+ /* Get block type */
+ $block_type = $block_to_be_deleted['type'];
+
+ /* Remove design settings and instances for this block */
+ self::delete_block_design_instances($block_id, $block_type);
+
+ return $query;
+
+ }
+
+
+ public static function delete_block_design_instances($block_id, $block_type) {
+
+ HeadwayElementAPI::register_elements_hook();
+
+ $block_element = HeadwayElementAPI::get_element('block-' . $block_type);
+
+ /* Start by queuing the instance of the block element */
+ $instances_to_delete = array(
+ 'block-' . $block_type => $block_type . '-block-' . $block_id
+ );
+
+ /* Find all block children element instances and queue them to be deleted */
+ foreach ( HeadwayElementAPI::get_block_elements($block_type) as $element_id => $element_info )
+ $instances_to_delete[$element_id] = $element_id . '-block-' . $block_id;
+
+ /* Delete the instances now */
+ foreach ( $instances_to_delete as $element_id => $instance_id )
+ HeadwayElementsData::delete_special_element_properties('blocks', $element_id, 'instance', $instance_id);
+
+ }
+
+
+ public static function delete_by_layout($layout_id) {
+
+ global $wpdb;
+
+ $layout_blocks = self::get_blocks_by_layout($layout_id);
+
+ foreach ( $layout_blocks as $block_id => $options ) {
+
+ //Delete design instances
+ self::delete_block_design_instances($block_id, $options['type']);
+
+ /* Unmirror the blocks mirroring this block */
+ $wpdb->update( $wpdb->hw_blocks, array(
+ 'mirror_id' => ''
+ ), array(
+ 'mirror_id' => $block_id
+ ));
+
+ }
+
+ //Query to delete blocks
+ $query = $wpdb->delete( $wpdb->hw_blocks, array(
+ 'template' => HeadwayOption::$current_skin,
+ 'layout' => $layout_id
+ ));
+
+ return $query;
+
+ }
+
+
+ public static function delete_by_wrapper($layout_id, $wrapper_id) {
+
+ global $wpdb;
+
+ $wrapper_blocks = self::get_blocks_by_layout($layout_id, $wrapper_id);
+
+ foreach ( $wrapper_blocks as $block_id => $options ) {
+
+ //Delete design instances
+ self::delete_block_design_instances($block_id, $options['type']);
+
+ /* Unmirror the blocks mirroring this block */
+ $wpdb->update( $wpdb->hw_blocks, array(
+ 'mirror_id' => ''
+ ), array(
+ 'mirror_id' => $block_id
+ ));
+
+
+ }
+
+ //Query to delete blocks
+ $query = $wpdb->delete( $wpdb->hw_blocks, array(
+ 'template' => HeadwayOption::$current_skin,
+ 'wrapper_id' => $wrapper_id,
+ 'layout' => $layout_id
+ ));
+
+ return $query;
+
+ }
+
+
+ public static function delete_by_template($template) {
+
+ global $wpdb;
+
+ return $wpdb->delete( $wpdb->hw_blocks, array(
+ 'template' => $template
+ ));
+
+ }
+
+
+ public static function get_block($block_id_or_obj, $use_mirrored = false) {
+
+ global $wpdb;
+
+ /* If a block array is supplied, make sure it is legitimate. */
+ if ( is_array( $block_id_or_obj) ) {
+
+ if ( !isset( $block_id_or_obj['id']) && !headway_get('new', $block_id_or_obj, false) )
+ return null;
+
+ $block = $block_id_or_obj;
+
+ /* Fetch the block based off of ID */
+ } elseif ( is_string( $block_id_or_obj) || is_numeric( $block_id_or_obj) ) {
+
+ /* Build cache key */
+ $cache_key = 'hw_block_' . $block_id_or_obj;
+
+ /* Check cache */
+ $block_from_cache = wp_cache_get($cache_key);
+
+ if ( $block_from_cache === false ) {
+
+ $block = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->hw_blocks WHERE template = '%s' AND id = '%s'", HeadwayOption::$current_skin, $block_id_or_obj), ARRAY_A);
+
+ if ( is_array($block) && !is_wp_error($block) ) {
+
+ $block = array_map('headway_maybe_unserialize', $block);
+
+ } else {
+
+ /* If no block is found, try querying the legacy_id */
+ $block_from_legacy_id = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->hw_blocks WHERE template = '%s' AND legacy_id = '%d'", HeadwayOption::$current_skin, $block_id_or_obj ), ARRAY_A );
+
+ if ( is_array($block_from_legacy_id) && ! is_wp_error( $block_from_legacy_id ) ) {
+ $block = array_map( 'headway_maybe_unserialize', $block_from_legacy_id );
+ } else {
+ $block = null;
+ }
+
+ }
+
+ wp_cache_set($cache_key, $block);
+
+ } else {
+
+ $block = $block_from_cache;
+
+ }
+
+ /* No valid argument provided. */
+ } else {
+
+ return null;
+
+ }
+
+ /* Fetch the mirrored block if $use_mirrored is true */
+ if ( $use_mirrored === true && $mirrored_block = self::get_block_mirror($block) )
+ $block = $mirrored_block;
+
+ return $block;
+
+ }
+
+
+ public static function get_blocks_by_layout($layout_id, $wrapper_id = false, $include_design_editor_instances = false) {
+
+ global $wpdb;
+
+ /* Build cache key */
+ $cache_key = 'hw_blocks_by_layout_' . $layout_id;
+
+ if ( $wrapper_id )
+ $cache_key = $cache_key . '_wrapper_' . $wrapper_id;
+
+ if ( $include_design_editor_instances )
+ $cache_key = $cache_key . '_with_design';
+
+ /* Check cache */
+ $layout_blocks = wp_cache_get($cache_key);
+
+ if ( $layout_blocks === false ) {
+
+ /* Retrieve all blocks from layout */
+ $query_string = $wpdb->prepare("SELECT * FROM $wpdb->hw_blocks WHERE layout = '%s' AND template = '%s'", $layout_id, HeadwayOption::$current_skin);
+
+ if ( $wrapper_id )
+ $query_string .= " AND wrapper_id = '$wrapper_id'";
+
+ $layout_blocks_query = $wpdb->get_results($query_string, ARRAY_A);
+
+ /* Change results array into associative */
+ $layout_blocks = array();
+
+ foreach ( $layout_blocks_query as $layout_block ) {
+
+ $layout_blocks[$layout_block['id']] = array_map('headway_maybe_unserialize', $layout_block);
+
+ /* Add design editor instance in if set to do so */
+ if ( $include_design_editor_instances ) {
+
+ $layout_blocks[$layout_block['id']]['styling'] = self::get_block_styling($layout_block);
+
+ }
+
+ }
+
+ wp_cache_set($cache_key, $layout_blocks);
+
+ }
+
+ return $layout_blocks;
+
+ }
+
+
+ public static function get_block_styling($block) {
+
+ do_action('headway_before_get_block_styling');
+
+ $block_element = HeadwayElementAPI::get_element('block-' . $block['type']);
+
+ /* Set up styling array */
+ $styling = array();
+
+ /* Get block instance styling */
+ $block_instance_properties = HeadwayElementsData::get_special_element_properties(array(
+ 'element' => 'block-' . $block['type'],
+ 'se_type' => 'instance',
+ 'se_meta' => $block['type'] . '-block-' . $block['id']
+ ));
+
+ if ( !empty($block_instance_properties) ) {
+
+ $styling[$block['type'] . '-block-' . $block['id']] = array(
+ 'element' => 'block-' . $block['type'],
+ 'properties' => $block_instance_properties
+ );
+
+ }
+
+ /* Get block children element instances (which could be a LOT) */
+ foreach ( HeadwayElementAPI::get_block_elements($block['type']) as $block_element_sub_element ) {
+
+ /* Make sure that the element supports instances */
+ if ( !headway_get('supports-instances', $block_element_sub_element) )
+ continue;
+
+ $sub_element_instance_id = $block_element_sub_element['id'] . '-block-' . $block['id'];
+
+ $sub_element_instance_properties = HeadwayElementsData::get_special_element_properties(array(
+ 'element' => $block_element_sub_element['id'],
+ 'se_type' => 'instance',
+ 'se_meta' => $sub_element_instance_id
+ ));
+
+ /* Only add sub element instance if there are properties present */
+ if ( !empty($sub_element_instance_properties) ) {
+
+ $styling[$sub_element_instance_id] = array(
+ 'element' => $block_element_sub_element['id'],
+ 'properties' => $sub_element_instance_properties
+ );
+
+ }
+
+ /* Instance states */
+ if ( !empty($block_element_sub_element['states']) && is_array($block_element_sub_element['states']) ) {
+
+ foreach ( $block_element_sub_element['states'] as $instance_state_id => $instance_state_info ) {
+
+ $actual_instance_id = $block_element_sub_element['id'] . '-block-' . $block['id'] . '-state-' . $instance_state_id;
+ $instance_state_properties = HeadwayElementsData::get_special_element_properties(array(
+ 'element' => $block_element_sub_element['id'],
+ 'se_type' => 'instance',
+ 'se_meta' => $actual_instance_id
+ ));
+
+ /* Only add instance state if there are properties present */
+ if ( empty($instance_state_properties) )
+ continue;
+
+ $styling[$actual_instance_id] = array(
+ 'element' => $block_element_sub_element['id'],
+ 'properties' => $instance_state_properties
+ );
+
+ }
+
+ }
+ /* End getting instance states */
+
+ }
+
+ return $styling;
+
+ }
+
+
+ public static function get_blocks_by_wrapper($layout_id, $wrapper_id) {
+
+ $layout_blocks = self::get_blocks_by_layout($layout_id);
+ $layout_wrappers = HeadwayWrappersData::get_wrappers_by_layout($layout_id);
+ $wrapper_blocks = array();
+
+ foreach ( $layout_blocks as $block_id => $block ) {
+
+ if ( headway_get('wrapper_id', $block, HeadwayWrappers::$default_wrapper_id) === $wrapper_id )
+ $wrapper_blocks[$block_id] = $block;
+
+ /* If there's only one wrapper and the block does not have a proper ID or is default, move it to that wrapper */
+ if ( count($layout_wrappers) === 1 && (headway_get('wrapper_id', $block) === null || headway_get('wrapper_id', $block) == 'wrapper-default') )
+ $wrapper_blocks[$block_id] = $block;
+
+ }
+
+ return $wrapper_blocks;
+
+ }
+
+
+ public static function get_blocks_by_type($type) {
+
+ global $wpdb;
+
+ /* Build cache key */
+ $cache_key = 'hw_blocks_by_type_' . $type;
+
+ /* Check cache */
+ $blocks_from_cache = wp_cache_get($cache_key);
+
+ if ( $blocks_from_cache === false ) {
+
+ $blocks_by_type_query = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_blocks WHERE template = '%s' AND type = '%s'", HeadwayOption::$current_skin, $type), ARRAY_A);
+
+ /* Change results array into associative */
+ $blocks_by_type = array();
+
+ foreach ( $blocks_by_type_query as $block ) {
+
+ $blocks_by_type[$block['id']] = array_map('headway_maybe_unserialize', $block);
+
+ }
+
+ wp_cache_set($cache_key, $blocks_by_type);
+
+ } else {
+
+ $blocks_by_type = $blocks_from_cache;
+
+ }
+
+ return $blocks_by_type;
+
+ }
+
+
+ public static function get_all_blocks() {
+
+ global $wpdb;
+
+ /* Build cache key */
+ $cache_key = 'hw_all_blocks';
+
+ /* Check cache */
+ $blocks_from_cache = wp_cache_get($cache_key);
+
+ if ( $blocks_from_cache === false ) {
+
+ $blocks_query = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_blocks WHERE template = '%s'", HeadwayOption::$current_skin), ARRAY_A);
+
+ /* Change results array into associative */
+ $all_blocks = array();
+
+ foreach ( $blocks_query as $block ) {
+
+ $all_blocks[$block['id']] = array_map('headway_maybe_unserialize', $block);
+
+ }
+
+ wp_cache_set($cache_key, $all_blocks);
+
+ } else {
+
+ $all_blocks = $blocks_from_cache;
+
+ }
+
+ return $all_blocks;
+
+ }
+
+
+ public static function is_block_mirrored($block) {
+
+ $block = self::get_block($block);
+ $block_settings = headway_get( 'settings', $block, array() );
+
+ /* Use mirror-block setting if present because it means the block is new or the setting has been updated and not saved yet */
+ if ( isset( $block_settings['mirror-block'] ) )
+ return $block_settings['mirror-block'];
+
+ if ( $mirrored_block_id = headway_get('mirror_id', $block) )
+ return $mirrored_block_id;
+
+ return false;
+
+ }
+
+
+ public static function get_block_mirror($block) {
+
+ $block = self::get_block($block);
+
+ if ( $mirrored_block_id = self::is_block_mirrored($block) )
+ return HeadwayBlocksData::get_block($mirrored_block_id);
+
+ return false;
+
+ }
+
+
+ public static function block_exists($id) {
+
+ if ( self::get_block($id) )
+ return true;
+
+ return false;
+
+ }
+
+
+ public static function get_block_name($block) {
+
+ $block = self::get_block($block);
+
+ //Create the default name by using the block type and ID
+ $default_name = HeadwayBlocks::block_type_nice($block['type']);
+
+ return headway_get('alias', headway_get('settings', $block, array()), $default_name);
+
+ }
+
+
+ public static function get_block_width($block) {
+
+ $block = self::get_block($block);
+
+ $block_grid_width = headway_get('width', $block['dimensions'], null);
+
+ if ( $block_grid_width === null )
+ return null;
+
+ /* Fetch the wrapper that way we can get its Grid settings */
+ $wrapper = HeadwayWrappersData::get_wrapper(headway_get('wrapper_id', $block, 'wrapper-default'));
+
+ $column_width = HeadwayWrappers::get_column_width($wrapper);
+ $gutter_width = HeadwayWrappers::get_gutter_width($wrapper);
+
+ return ( $block_grid_width * ($column_width + $gutter_width) ) - $gutter_width;
+
+ }
+
+
+ public static function get_block_height($block) {
+
+ $block = self::get_block($block);
+
+ $block_grid_height = headway_get('height', $block['dimensions'], null);
+
+ if ( $block_grid_height === null )
+ return null;
+
+ return $block_grid_height;
+
+ }
+
+
+ public static function get_block_setting($block, $setting, $default = null) {
+
+ $block = self::get_block($block);
+
+ //No block, no settings
+ if ( !$block )
+ return $default;
+
+ if ( !isset($block['settings'][$setting]) )
+ return $default;
+
+ return headway_fix_data_type($block['settings'][$setting]);
+
+ }
+
+
+ public static function get_legacy_id($block) {
+
+ return is_numeric( headway_get( 'legacy_id', $block ) ) && headway_get( 'legacy_id', $block ) > 0 ? headway_get( 'legacy_id', $block ) : $block['id'];
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-elements.php b/wp-content/themes/headway/library/data/data-elements.php
new file mode 100644
index 0000000..093e72d
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-elements.php
@@ -0,0 +1,343 @@
+ $element_options ) {
+
+ $element = HeadwayElementAPI::get_element($element_id);
+
+ if ( !isset($element['default-element']) || $element['default-element'] === false )
+ continue;
+
+ $temp_id = $element_id;
+ $temp_options = $element_options;
+
+ unset($elements[$element_id]);
+
+ $elements = array_merge(array($temp_id => $temp_options), $elements);
+
+ }
+
+ return $elements;
+
+ }
+
+
+ public static function get_element_properties($element) {
+
+ //Get element ID
+ $element_id = is_array($element) ? $element['id'] : $element;
+
+ $element = headway_get($element_id, self::get_raw_data());
+
+ if ( !isset($element['properties']) || !is_array($element['properties']) )
+ $element['properties'] = array();
+
+ $properties = $element['properties'];
+
+ //Fetch the property
+ return ( is_array($properties) && count($properties) > 0 ) ? $properties : array();
+
+ }
+
+
+ public static function get_special_element_properties($args) {
+
+ $defaults = array(
+ 'element' => null,
+ 'se_type' => null,
+ 'se_meta' => null
+ );
+
+ extract(array_merge($defaults, $args));
+
+ //Get element ID
+ $element_id = is_array($element) ? $element['id'] : $element;
+
+ $element = headway_get($element_id, self::get_raw_data(), array(
+ 'special-element-' . $se_type => array()
+ ));
+
+ if ( !isset($element['special-element-' . $se_type][$se_meta]) || !is_array($element['special-element-' . $se_type][$se_meta]) )
+ $element['special-element-' . $se_type][$se_meta] = array();
+
+ $properties =& $element['special-element-' . $se_type][$se_meta];
+
+ //Return the data
+ return ( is_array($properties) && count($properties) > 0 ) ? $properties : array();
+
+ }
+
+
+ /* Single Get */
+ public static function get_property($element_id, $property_id, $default = null, $element_group = null) {
+
+ $properties = self::get_element_properties($element_id);
+
+ if ( $properties !== null && !is_wp_error($properties) && isset($properties[$property_id]) && (headway_fix_data_type($properties[$property_id]) || headway_fix_data_type($properties[$property_id]) === 0) )
+ return headway_fix_data_type($properties[$property_id]);
+
+ else
+ return $default;
+
+ }
+
+
+ public static function get_special_element_property($element_id, $se_type, $se_meta, $property_id, $default = null, $element_group = null) {
+
+ $properties = self::get_special_element_properties(array(
+ 'element' => $element_id,
+ 'se_type' => $se_type,
+ 'se_meta' => $se_meta
+ ));
+
+ if ( $properties !== null && !is_wp_error($properties) && isset($properties[$property_id]) && (headway_fix_data_type($properties[$property_id]) || headway_fix_data_type($properties[$property_id]) === 0) )
+ return headway_fix_data_type($properties[$property_id]);
+
+ else
+ return $default;
+
+ }
+
+
+ /* Setting */
+ public static function set_property($element_group = null, $element_id, $property_id, $value) {
+
+ /* Pass the torch onto self::delete_property() if the value is 'delete' */
+ if ( strtolower($value) == 'delete' )
+ return self::delete_property($element_id, $property_id);
+
+ $all_properties = HeadwaySkinOption::get('properties', 'design', array());
+
+ /* Insure array exists for element that property is being set for */
+ if ( !isset($all_properties[$element_id]) || !is_array($all_properties[$element_id]) )
+ $all_properties[$element_id] = array('properties' => array());
+
+ /* Set the property */
+ if ( $value == 'null' )
+ $value = null;
+
+ $all_properties[$element_id]['properties'][$property_id] = $value;
+
+ /* Send it back to DB */
+ return HeadwaySkinOption::set('properties', $all_properties, 'design');
+
+ }
+
+
+ public static function delete_property($element_id, $property_id) {
+
+ $all_properties = HeadwaySkinOption::get('properties', 'design', array());
+
+ /* Delete the property */
+ if ( !empty($all_properties[$element_id]['properties']) && isset($all_properties[$element_id]['properties'][$property_id]) )
+ unset($all_properties[$element_id]['properties'][$property_id]);
+
+ /* Send it back to DB */
+ return HeadwaySkinOption::set('properties', $all_properties, 'design');
+
+ }
+
+
+ public static function set_special_element_property($element_group = null, $element_id, $special_element_type, $special_element_meta, $property_id, $value) {
+
+ /* Pass the torch onto self::delete_special_element_property() if the value is 'delete' */
+ if ( strtolower($value) == 'delete' )
+ return self::delete_special_element_property(null, $element_id, $special_element_type, $special_element_meta, $property_id);
+
+ $all_properties = HeadwaySkinOption::get('properties', 'design', array());
+
+ /* Insure array exists for element that property is being set for */
+ if ( !isset($all_properties[$element_id]) || !is_array($all_properties[$element_id]) )
+ $all_properties[$element_id] = array('special-element-' . $special_element_type => array(
+ $special_element_meta => array()
+ ));
+
+ /* Set the property */
+ if ( $value == 'null' )
+ $value = null;
+
+ $all_properties[$element_id]['special-element-' . $special_element_type][$special_element_meta][$property_id] = $value;
+
+ /* Send it back to DB */
+ return HeadwaySkinOption::set('properties', $all_properties, 'design');
+
+ }
+
+
+ public static function delete_special_element_property($element_group = null, $element_id, $special_element_type, $special_element_meta, $property_id) {
+
+ $all_properties = HeadwaySkinOption::get('properties', 'design', array());
+
+ if ( isset($all_properties[$element_id]['special-element-' . $special_element_type][$special_element_meta][$property_id]) )
+ unset($all_properties[$element_id]['special-element-' . $special_element_type][$special_element_meta][$property_id]);
+
+ /* Send it back to DB */
+ return HeadwaySkinOption::set('properties', $all_properties, 'design');
+
+ }
+
+
+ public static function delete_special_element_properties($element_group = null, $element_id, $special_element_type, $special_element_meta) {
+
+ $all_properties = HeadwaySkinOption::get('properties', 'design', array());
+
+ /* Delete all special elements matching the meta and type */
+ if ( isset($all_properties[$element_id]['special-element-' . $special_element_type][$special_element_meta]) )
+ unset($all_properties[$element_id]['special-element-' . $special_element_type][$special_element_meta]);
+
+ /* Send it back to DB */
+ return HeadwaySkinOption::set('properties', $all_properties, 'design');
+
+ }
+
+
+ /* Defaults */
+ public static function get_default_data() {
+
+ global $headway_core_default_element_data;
+
+ return $headway_core_default_element_data;
+
+ }
+
+
+ public static function get_legacy_default_data() {
+
+ global $headway_default_element_data;
+
+ if ( !isset($headway_default_element_data) || !is_array($headway_default_element_data) )
+ $headway_default_element_data = array();
+
+ return apply_filters('headway_element_data_defaults', $headway_default_element_data);
+
+ }
+
+
+ /**
+ * Merge in default design data. This will be ran upon save and upgrade to Headway 3.6
+ */
+ public static function merge_core_default_design_data() {
+
+ self::merge_default_design_data(HeadwayElementsData::get_default_data(), 'core');
+
+ self::merge_default_design_data( array(
+ 'block-pin-board-pin' => array(
+ 'properties' => array(
+ 'padding-top' => 1,
+ 'padding-right' => 1,
+ 'padding-bottom' => 1,
+ 'padding-left' => 1,
+ 'background-color' => 'ffffff',
+ 'border-color' => 'eeeeee',
+ 'border-style' => 'solid',
+ 'border-top-width' => 1,
+ 'border-right-width' => 1,
+ 'border-bottom-width' => 1,
+ 'border-left-width' => 1,
+ 'box-shadow-color' => 'eee',
+ 'box-shadow-blur' => 3,
+ 'box-shadow-horizontal-offset' => 0,
+ 'box-shadow-vertical-offset' => 2
+ )
+ ),
+ 'block-pin-board-pin-title' => array(
+ 'properties' => array(
+ 'padding-top' => 15,
+ 'padding-right' => 15,
+ 'padding-left' => 15,
+ 'font-size' => 18,
+ 'line-height' => 120,
+ 'text-decoration' => 'none'
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'text-decoration' => 'underline'
+ )
+ )
+ ),
+ 'block-pin-board-pin-text' => array(
+ 'properties' => array(
+ 'font-size' => 12,
+ 'line-height' => 150,
+ 'padding-right' => 15,
+ 'padding-left' => 15
+ )
+ ),
+ 'block-pin-board-pin-meta' => array(
+ 'properties' => array(
+ 'font-size' => 12,
+ 'line-height' => 120,
+ 'padding-right' => 15,
+ 'padding-left' => 15,
+ 'color' => '888888'
+ )
+ ),
+ 'block-pin-board-pagination-button' => array(
+ 'properties' => array(
+ 'text-decoration' => 'none',
+ 'background-color' => 'eeeeee',
+ 'border-top-left-radius' => 4,
+ 'border-top-right-radius' => 4,
+ 'border-bottom-right-radius' => 4,
+ 'border-bottom-left-radius' => 4,
+ 'padding-top' => 5,
+ 'padding-right' => 9,
+ 'padding-bottom' => 5,
+ 'padding-left' => 9
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'background-color' => 'e7e7e7'
+ )
+ )
+ )
+ ), 'core-37-pin-board' );
+
+ }
+
+
+ /* This function accepts data as well as ID that way it can be used by Headway plugins */
+ public static function merge_default_design_data($default_data, $id) {
+
+ $merge_id = 'merged-default-design-data-' . strtolower(str_replace(array(' ', '-'), '_', $id));
+
+ /* Only merge if it hasn't been merged before. */
+ if ( !HeadwaySkinOption::get($merge_id, 'general', false) ) {
+
+ $design_data = HeadwaySkinOption::get('properties', 'design', array());
+ $design_data_with_defaults = headway_array_merge_recursive_simple($default_data, $design_data);
+
+ HeadwaySkinOption::set($merge_id, true, 'general');
+
+ return HeadwaySkinOption::set('properties', $design_data_with_defaults, 'design');
+
+ }
+
+ /* Already merged, return false */
+ return false;
+
+ }
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-layout-options.php b/wp-content/themes/headway/library/data/data-layout-options.php
new file mode 100644
index 0000000..eb84c29
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-layout-options.php
@@ -0,0 +1,255 @@
+get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_layout_meta WHERE layout = '%s' AND template = '%s'", $layout, $template), ARRAY_A);
+
+ if ( is_wp_error($options) || !is_array($options) || !count($options) ) {
+ wp_cache_set($cache_key, array());
+ return $default;
+ }
+
+ /* Loop through results and make it into an associative array */
+ $layout_options = array();
+
+ foreach ( $options as $option_row ) {
+ $layout_options[$option_row['meta_key']] = $option_row['meta_value'];
+ }
+
+ wp_cache_set($cache_key, $layout_options);
+
+ }
+
+ if ( !isset($layout_options[$option]) )
+ return $default;
+
+ $return = $layout_options[$option];
+
+ }
+
+ return headway_fix_data_type($return);
+
+ }
+
+
+ public static function set($layout, $option, $value, $global = false, $group_prefix = false, $template = null) {
+
+ if ( !$template )
+ $template = self::$current_skin;
+
+ if ( $group_prefix && $group_prefix != 'general' )
+ $option = $group_prefix . '_' . $option;
+
+ /* If it's post meta compatible, then use WP functions */
+ if ( $post_id = self::is_post($layout) ) {
+
+ $option = self::postmeta_option($option, $global, $template);
+
+ return update_post_meta($post_id, $option, $value);
+
+ /* Otherwise use the Headway layout meta table */
+ } else {
+
+ global $wpdb;
+
+ $template = $global ? '' : $template;
+
+ /* Check if option exists. If it does, use $wpdb->update, otherwise use $wpdb->insert */
+ if ( $meta_id = $wpdb->get_var($wpdb->prepare("SELECT meta_id FROM $wpdb->hw_layout_meta WHERE layout = '%s' AND template = '%s' AND meta_key = '%s'", $layout, $template, $option)) ) {
+
+ return $wpdb->update($wpdb->hw_layout_meta, array(
+ 'meta_value' => headway_maybe_serialize($value)
+ ), array(
+ 'meta_id' => $meta_id
+ ));
+
+ } else {
+
+ return $wpdb->insert($wpdb->hw_layout_meta, array(
+ 'meta_key' => $option,
+ 'meta_value' => headway_maybe_serialize($value),
+ 'layout' => $layout,
+ 'template' => $template
+ ));
+
+ }
+
+ }
+
+ }
+
+
+ public static function delete($layout, $option, $global = false) {
+
+ /* If it's post meta compatible, then use WP functions */
+ if ( $post_id = self::is_post($layout) ) {
+
+ $option = self::postmeta_option($option, $global);
+
+ return delete_post_meta($post_id, $option);
+
+ /* Otherwise use the Headway layout meta table */
+ } else {
+
+ global $wpdb;
+
+ $template = $global ? '' : self::$current_skin;
+
+ return $wpdb->delete($wpdb->hw_layout_meta, array(
+ 'layout' => $layout,
+ 'meta_key' => $option,
+ 'template' => $template
+ ));
+
+ }
+
+ }
+
+
+ public static function delete_all_from_layout($layout, $global = false) {
+
+ /* If it's post meta compatible, then use WP functions */
+ if ( $post_id = self::is_post($layout) ) {
+
+ $options = get_post_custom($post_id);
+ $options_deleted = array();
+
+ $key_prefix_to_check = $global ? '_hw_' : '_hw_|template=' . self::$current_skin . '|_';
+
+ foreach ( $options as $meta_key => $meta_id ) {
+
+ if ( strpos($meta_key, $key_prefix_to_check) !== 0 )
+ continue;
+
+ $options_deleted = delete_post_meta($post_id, $meta_key);
+
+ }
+
+ return $options_deleted;
+
+ /* Otherwise use the Headway layout meta table */
+ } else {
+
+ global $wpdb;
+
+ if ( $global ) {
+
+ return $wpdb->delete($wpdb->hw_layout_meta, array(
+ 'layout' => $layout
+ ));
+
+ } else {
+
+ return $wpdb->delete($wpdb->hw_layout_meta, array(
+ 'layout' => $layout,
+ 'template' => self::$current_skin
+ ));
+
+ }
+
+ }
+
+ }
+
+
+ public static function delete_by_template($template) {
+
+ global $wpdb;
+
+ $wpdb->delete($wpdb->hw_layout_meta, array(
+ 'template' => $template
+ ));
+
+ $wpdb->query($wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_key LIKE '%s'", '_hw_|template=' . $template . '|_%'));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-options.php b/wp-content/themes/headway/library/data/data-options.php
new file mode 100644
index 0000000..2ab7798
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-options.php
@@ -0,0 +1,197 @@
+blog_id, $option);
+
+ return get_option($option);
+
+ }
+
+
+ public static function get_from_main_site($option = null, $group_name = false, $default = null) {
+
+ return self::get($option, $group_name, $default, false, true);
+
+ }
+
+
+ /**
+ * Add or update an option on the database.
+ *
+ * @param string Option to set
+ * @param mixed Value to attach to option
+ * @param string Group to add/update the option to
+ *
+ * @return bool
+ **/
+ public static function set($option = null, $value = null, $group_name = false) {
+
+ if ( $option === null )
+ return false;
+
+ if ( $value === null )
+ return false;
+
+ if ( !$group_name )
+ $group_name = self::$default_group;
+
+ $group_option_name = self::format_wp_option('headway_option_group_' . $group_name);
+
+ /* Pull in existing data so we can add on top of it */
+ $group_data = get_option($group_option_name, array());
+
+ /* Handle boolean values */
+ if ( is_bool($value) )
+ $value = ( $value === true ) ? 'true' : 'false';
+
+ /* Add option */
+ $group_data[$option] = $value;
+
+ /* Send group option to DB */
+ return update_option($group_option_name, $group_data);
+
+ }
+
+
+ public static function set_group($group_name, $group_data) {
+
+ $group_option_name = self::format_wp_option('headway_option_group_' . $group_name);
+
+ return update_option($group_option_name, $group_data);;
+
+ }
+
+
+ /**
+ * Delete option from database.
+ *
+ * @param string Option to delete
+ * @param string Group to delete from
+ *
+ * @return bool
+ **/
+ public static function delete($option = null, $group_name = false) {
+
+ //return wp_die('Deleting some shit right now. Trying: ' . $option);
+
+ if ( $option === null )
+ return false;
+
+ if ( !$group_name )
+ $group_name = self::$default_group;
+
+ $option_name = self::format_wp_option('headway_option_group_' . $group_name);
+ $group_data = get_option($option_name);
+
+ //If the group isn't in the DB or the option doesn't exist
+ if( !is_array($group_data) || !isset($group_data[$option]) )
+ return false;
+
+ //Delete option from group
+ unset($group_data[$option]);
+
+ //If the array is still fine and not empty, just update the group on the DB
+ if ( count($group_data) !== 0 )
+ return update_option($option_name, $group_data);
+
+ //Remove group from DB
+ return delete_option($option_name);
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-portability.php b/wp-content/themes/headway/library/data/data-portability.php
new file mode 100644
index 0000000..4f005a5
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-portability.php
@@ -0,0 +1,452 @@
+ HEADWAY_VERSION,
+ 'name' => headway_get('name', $info, 'Unnamed'),
+ 'author' => headway_get('author', $info),
+ 'image-url' => headway_get('image-url', $info),
+ 'version' => headway_get('version', $info),
+ 'data_wp_options' => $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->options WHERE option_name LIKE '%s'", $wp_options_prefix . '%'), ARRAY_A),
+ 'data_wp_postmeta' => $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '%s'", '_hw_|template=' . HeadwayOption::$current_skin . '|_%'), ARRAY_A),
+ 'data_hw_layout_meta' => $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_layout_meta WHERE template = '%s'", HeadwayOption::$current_skin), ARRAY_A),
+ 'data_hw_wrappers' => $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_wrappers WHERE template = '%s'", HeadwayOption::$current_skin), ARRAY_A),
+ 'data_hw_blocks' => $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_blocks WHERE template = '%s'", HeadwayOption::$current_skin), ARRAY_A)
+ );
+
+ /* Spit the file out */
+ $filename = 'Headway Template - ' . headway_get('name', $info, 'Unnamed');
+
+ if ( headway_get('version', $info) ) {
+ $filename .= ' ' . headway_get('version', $info);
+ }
+
+ return self::to_json($filename, 'skin', $skin);
+
+ }
+
+
+ public static function install_skin(array $skin) {
+
+ $skins = HeadwayOption::get_group('skins');
+
+ /* Remove image definitions */
+ if ( isset($skin['image-definitions']) )
+ unset($skin['image-definitions']);
+
+ /* Skin ID ... Truncate the skin ID to 12 characters due to varchar limit in wp_options */
+ $original_skin_id = substr(strtolower(str_replace(' ', '-', $skin['name'])), 0, 12);
+
+ $skin_id = $original_skin_id;
+ $skin_name = $skin['name'];
+
+ $skin_unique_id_counter = 0;
+
+ /* Check if skin already exists. If it does, change ID and skin name */
+ while ( HeadwayOption::get($skin_id, 'skins') || get_option('headway_|template=' . $skin_id . '|_option_group_general') ) {
+
+ $skin_unique_id_counter++;
+ $skin_id = $original_skin_id . '-' . $skin_unique_id_counter;
+
+ $skin_name = $skin['name'] . ' ' . $skin_unique_id_counter;
+
+ }
+
+ /* Send skin to DB */
+ $skin['id'] = $skin_id;
+ $skin['name'] = $skin_name;
+
+ $skin_with_info_only = $skin;
+
+ $data_to_remove_from_saved_skin = array(
+ 'data_wp_options',
+ 'data_wp_postmeta',
+ 'data_hw_layout_meta',
+ 'data_hw_wrappers',
+ 'data_hw_blocks',
+ 'templates',
+ 'layouts',
+ 'element-data'
+ );
+
+ foreach ( $data_to_remove_from_saved_skin as $key_to_remove ) {
+
+ if ( !isset($skin_with_info_only[$key_to_remove]) )
+ continue;
+
+ unset($skin_with_info_only[$key_to_remove]);
+
+ }
+
+ HeadwayOption::set($skin['id'], $skin_with_info_only, 'skins');
+
+ /* Change current skin ID to the newly added skin so we can populate data */
+ HeadwayOption::$current_skin = $skin['id'];
+ HeadwayLayoutOption::$current_skin = $skin['id'];
+
+ /* Process the install */
+ if ( !headway_get('hw-version', $skin) || version_compare(headway_get('hw-version', $skin), '3.7', '<') ) {
+ $skin = self::process_install_skin_pre37($skin);
+ } else {
+ $skin = self::process_install_skin($skin);
+ }
+
+ /* Change $current_skin back just to be safe */
+ HeadwayOption::$current_skin = HeadwayTemplates::get_active_id();
+ HeadwayLayoutOption::$current_skin = HeadwayTemplates::get_active_id();
+
+ return $skin;
+
+ }
+
+
+ public static function process_install_skin_pre37(array $skin) {
+
+ /* Set up skin options that way when it's activated it looks right */
+ /* Install templates */
+ if ( $skin_templates = headway_get('templates', $skin) )
+ HeadwaySkinOption::set_group('templates', $skin_templates);
+
+ /* Assign templates */
+ if ( !empty($skin['templates']['assignments']) ) {
+
+ foreach ( $skin['templates']['assignments'] as $layout_id => $template_id ) {
+
+ /* Change layout ID separators */
+ if ( strpos($layout_id, 'template-') !== 0 )
+ $layout_id = str_replace('-', HeadwayLayout::$sep, $layout_id);
+
+ HeadwayLayoutOption::set($layout_id, 'template', $template_id);
+
+ }
+
+ }
+
+ /* Install layouts (blocks, wrappers, and flags */
+ $wrapper_id_mapping = array();
+ $block_id_mapping = array();
+
+ foreach ( $skin['layouts'] as $layout_id => $layout_data ) {
+
+ /* Change layout ID separators */
+ if ( strpos($layout_id, 'template-') !== 0 )
+ $layout_id = str_replace('-', HeadwayLayout::$sep, $layout_id);
+
+ /* Install Wrappers */
+ foreach ( $layout_data['wrappers'] as $wrapper_id => $wrapper_data ) {
+
+ $wrapper_data['position'] = array_search($wrapper_id, array_keys($layout_data['wrappers']));
+
+ $wrapper_data['settings'] = array(
+ 'fluid' => headway_get('fluid', $wrapper_data),
+ 'fluid-grid' => headway_get('fluid-grid', $wrapper_data),
+ 'columns' => headway_get('columns', $wrapper_data),
+ 'column-width' => headway_get('column-width', $wrapper_data),
+ 'gutter-width' => headway_get('gutter-width', $wrapper_data),
+ 'use-independent-grid' => headway_get('use-independent-grid', $wrapper_data)
+ );
+
+ $new_wrapper = HeadwayWrappersData::add_wrapper($layout_id, $wrapper_data);
+
+ if ( $new_wrapper && !is_wp_error($new_wrapper) ) {
+ $wrapper_id_mapping[HeadwayWrappers::format_wrapper_id($wrapper_id)] = $new_wrapper;
+ }
+
+ }
+
+ /* Install Blocks */
+ foreach ( $layout_data['blocks'] as $block_id => $block_data ) {
+
+ $block_data['wrapper'] = headway_get(HeadwayWrappers::format_wrapper_id(headway_get('wrapper', $block_data)), $wrapper_id_mapping);
+
+ $new_block = HeadwayBlocksData::add_block($layout_id, $block_data);
+
+ if ( $new_block && !is_wp_error($new_block) ) {
+ $block_id_mapping[$block_id] = $new_block;
+ }
+
+ }
+
+ }
+
+ /* Setup mirroring */
+ foreach ( $skin['layouts'] as $layout_id => $layout_data ) {
+
+ /* Change layout ID separators */
+ if (strpos($layout_id, 'template-') !== 0)
+ $layout_id = str_replace('-', HeadwayLayout::$sep, $layout_id);
+
+ foreach ($layout_data['wrappers'] as $wrapper_id => $wrapper_data) {
+
+ $wrapper_to_update = $wrapper_id_mapping[HeadwayWrappers::format_wrapper_id($wrapper_id)];
+
+ if (!$mirror_id = headway_get('mirror-wrapper', $wrapper_data))
+ continue;
+
+ $mirror_id = headway_get(HeadwayWrappers::format_wrapper_id($mirror_id), $wrapper_id_mapping);
+
+ HeadwayWrappersData::update_wrapper($wrapper_to_update, array(
+ 'mirror_id' => $mirror_id
+ ));
+
+ }
+
+ foreach ( $layout_data['blocks'] as $block_id => $block_data ) {
+
+ if ( !isset($block_id_mapping[$block_id]) )
+ continue;
+
+ $block_to_update = $block_id_mapping[$block_id];
+
+ if ( !$mirror_id = headway_get('mirror-block', headway_get('settings', $block_data, array())) )
+ continue;
+
+ $mirror_id = headway_get($mirror_id, $block_id_mapping);
+
+ HeadwayBlocksData::update_block($block_to_update, array(
+ 'mirror_id' => $mirror_id
+ ));
+
+ }
+
+ }
+
+ /* Install design data */
+ /* Sort the block and wrapper mappings by descending number that way when we do a simple recursive find and replace the small block IDs won't mess up the larger block IDs.
+ Example: Replacing block-1 before block-11 is replaced would be bad news */
+ krsort($block_id_mapping);
+ krsort($wrapper_id_mapping);
+
+ foreach ( $block_id_mapping as $old_block_id => $new_block_id ) {
+ $skin['element-data'] = headway_str_replace_json('block-' . $old_block_id, 'block-' . $new_block_id, $skin['element-data']);
+ }
+
+ foreach ( $wrapper_id_mapping as $old_wrapper_id => $new_wrapper_id ) {
+ $skin['element-data'] = headway_str_replace_json('wrapper-' . $old_wrapper_id, 'wrapper-' . $new_wrapper_id, $skin['element-data']);
+ }
+
+ $skin['element-data'] = headway_preg_replace_json( "/-layout-[\w-]*/", '', $skin['element-data'] );
+
+ HeadwaySkinOption::set('properties', $skin['element-data'], 'design');
+ HeadwaySkinOption::set('live-css', stripslashes($skin['live-css']));
+
+ /* Set merge flag that way the next time they save it won't screw up the styling */
+ HeadwaySkinOption::set('merged-default-design-data-core', true, 'general');
+
+ /* Set wrapper defaults */
+ if ( !empty($skin['wrapper-defaults']) && is_array($skin['wrapper-defaults']) ) {
+
+ HeadwaySkinOption::set('columns', headway_get('columns', $skin['wrapper-defaults'], HeadwayWrappers::$default_columns));
+ HeadwaySkinOption::set('columns-width', headway_get('columns', $skin['wrapper-defaults'], HeadwayWrappers::$default_columns));
+ HeadwaySkinOption::set('gutter-width', headway_get('columns', $skin['wrapper-defaults'], HeadwayWrappers::$default_columns));
+
+ }
+
+ return $skin;
+
+ }
+
+
+
+ public static function process_install_skin(array $skin) {
+
+ return HeadwayDataSnapshots::process_rollback($skin, $skin['id']);
+
+ }
+
+
+ public static function export_block_settings($block_id) {
+
+ /* Set up variables */
+ $block = HeadwayBlocksData::get_block($block_id);
+
+ /* Check if block exists */
+ if ( !$block )
+ die('Error: Could not export block settings.');
+
+ /* Spit the file out */
+ return self::to_json('Block Settings - ' . HeadwayBlocksData::get_block_name($block), 'block-settings', array(
+ 'id' => $block_id,
+ 'type' => $block['type'],
+ 'settings' => $block['settings'],
+ 'styling' => HeadwayBlocksData::get_block_styling($block)
+ ));
+
+ }
+
+
+ public static function export_layout($layout_id) {
+
+ /* Set up variables */
+ if ( !$layout_name = HeadwayLayout::get_name($layout_id) )
+ die('Error: Invalid layout.');
+
+ $layout = array(
+ 'name' => $layout_name,
+ 'blocks' => HeadwayBlocksData::get_blocks_by_layout($layout_id)
+ );
+
+ /* Convert all mirrored blocks into original blocks by pulling their mirror target's settings */
+ /* Loop through each block in the template and check if it's mirrored. If it is, replace it with the block that it's mirroring */
+ foreach ( $layout['blocks'] as $layout_block_index => $layout_block ) {
+
+ if ( !$mirrored_block = HeadwayBlocksData::get_block_mirror($layout_block) )
+ continue;
+
+ $layout['blocks'][$layout_block_index] = $mirrored_block;
+
+ }
+
+ /* Spit the file out */
+ return self::to_json('Headway Layout - ' . $layout_name, 'layout', $layout);
+
+ }
+
+
+ /**
+ * Convert array to JSON file and force download.
+ *
+ * Images will be converted to base64 via HeadwayDataPortability::encode_images()
+ **/
+ public static function to_json($filename, $data_type = null, $array) {
+
+ if ( !$array['data-type'] = $data_type )
+ die('Missing data type for HeadwayDataPortability::to_json()');
+
+ $array['image-definitions'] = self::encode_images($array);
+
+ header('Content-Disposition: attachment; filename="' . $filename . '.json"');
+ header('Content-Type: application/json');
+ header('Pragma: no-cache');
+
+ echo json_encode($array);
+
+ return $filename;
+
+ }
+
+
+ /**
+ * Convert all images to base64.
+ *
+ * This method is recursive.
+ **/
+ public static function encode_images(&$array, $images = null) {
+
+ if ( !$images )
+ $images = array();
+
+ foreach ( $array as $key => $value ) {
+
+ $is_serialized = is_serialized($value);
+
+ if ( is_array($value) || $is_serialized ) {
+
+ if ( $is_serialized ) {
+
+ $value = headway_maybe_unserialize($value);
+
+ if ( !is_array($value) ) {
+ continue;
+ }
+
+ $array[$key] = $value;
+
+ }
+
+ $images = array_merge($images, self::encode_images($array[$key], $images));
+
+ continue;
+
+ } else if ( is_string($value) ) {
+
+ $image_matches = array();
+
+ /* PREG_SET_ORDER makes the $image_matches array make more sense */
+ preg_match_all('/([a-z\-_0-9\/\:\.]*\.(jpg|jpeg|png|gif))/i', $value, $image_matches, PREG_SET_ORDER);
+
+ /* Go through each image in the string and download it then base64 encode it and replace the URL with variable */
+ foreach ( $image_matches as $image_match ) {
+
+ if ( !count($image_match) )
+ continue;
+
+ $image_request = wp_remote_get($image_match[0]);
+
+ if ( $image_request && $image_contents = wp_remote_retrieve_body($image_request) ) {
+
+ $image = array(
+ 'base64_contents' => base64_encode($image_contents),
+ 'mime_type' => $image_request['headers']['content-type']
+ );
+
+ /* Add base64 encoded image to image definitions. */
+ /* Make sure that the image isn't already in the definitions. If it is, $possible_duplicate will be the key/ID to the image */
+ if ( !$possible_duplicate = array_search($image, $images) )
+ $images['%%IMAGE_REPLACEMENT_' . (count($images) + 1) . '%%'] = $image;
+
+ /* Replace the URL with variable that way it can be replaced with uploaded image on import. If $possible_duplicate isn't null/false, then use it! */
+ $variable = $possible_duplicate ? $possible_duplicate : '%%IMAGE_REPLACEMENT_' . (count($images)) . '%%';
+ $array[$key] = str_replace($image_match[0], $variable, $array[$key]);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return $images;
+
+ }
+
+
+ /**
+ * Convert base64 encoded image into a file and move it to proper WP uploads directory.
+ **/
+ public static function decode_image_to_uploads($base64_string) {
+
+ /* Make sure user has permissions to edit in the Visual Editor */
+ if ( !HeadwayCapabilities::can_user_visually_edit() )
+ return;
+
+ /* Create a temporary file and decode the base64 encoded image into it */
+ $temporary_file = wp_tempnam();
+ file_put_contents($temporary_file, base64_decode($base64_string));
+
+ /* Use wp_check_filetype_and_ext() to figure out the real mimetype of the image. Provide a bogus extension and then we'll use the 'proper_filename' later. */
+ $filename = 'headway-imported-image.jpg';
+ $file_information = wp_check_filetype_and_ext($temporary_file, $filename);
+
+ /* Construct $file array which is similar to a PHP $_FILES array. This array must be a variable since wp_handle_sideload() requires a variable reference argument. */
+ if ( headway_get('proper_filename', $file_information) )
+ $filename = $file_information['proper_filename'];
+
+ $file = array(
+ 'name' => $filename,
+ 'tmp_name' => $temporary_file
+ );
+
+ /* Let WordPress move the image and spit out the file path, URL, etc. Set test_form to false that way it doesn't verify $_POST['action'] */
+ $upload = wp_handle_sideload($file, array('test_form' => false));
+
+ /* If there's an error, be sure to unlink/delete the temporary file in case wp_handle_sideload() doesn't. */
+ if ( isset($upload['error']) )
+ @unlink($temporary_file);
+
+ return $upload;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-skin-options.php b/wp-content/themes/headway/library/data/data-skin-options.php
new file mode 100644
index 0000000..c220939
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-skin-options.php
@@ -0,0 +1,60 @@
+get_results($wpdb->prepare("SELECT id, timestamp, comments FROM $wpdb->hw_snapshots WHERE template = '%s' ORDER BY timestamp DESC", HeadwayOption::$current_skin));
+
+ }
+
+
+ public static function save_snapshot($throttle = false) {
+
+ global $wpdb;
+
+ /* Only allow snapshots to be saved every 15 minutes if $throttle is true */
+ if ( $throttle && $last_snapshot_timestamp = HeadwaySkinOption::get('last-snapshot') ) {
+
+ if ( time() < strtotime('+15 minutes', $last_snapshot_timestamp) )
+ return false;
+
+ }
+
+ $wp_options_prefix = 'headway_|template=' . HeadwayOption::$current_skin . '|_';
+
+ $insert_args = array(
+ 'template' => HeadwayOption::$current_skin,
+ 'comments' => headway_post('snapshot_comments'),
+ 'timestamp' => current_time('mysql', 1), /* GMT */
+ 'data_wp_options' => headway_maybe_serialize($wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->options WHERE option_name LIKE '%s'", $wp_options_prefix . '%'))),
+ 'data_wp_postmeta' => headway_maybe_serialize($wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '%s'", '_hw_|template=' . HeadwayOption::$current_skin . '|_%'))),
+ 'data_hw_layout_meta' => headway_maybe_serialize($wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_layout_meta WHERE template = '%s'", HeadwayOption::$current_skin))),
+ 'data_hw_wrappers' => headway_maybe_serialize($wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_wrappers WHERE template = '%s'", HeadwayOption::$current_skin))),
+ 'data_hw_blocks' => headway_maybe_serialize($wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_blocks WHERE template = '%s'", HeadwayOption::$current_skin)))
+ );
+
+ $snapshotquery = $wpdb->insert($wpdb->hw_snapshots, $insert_args);
+
+ if ( is_wp_error($snapshotquery) ) {
+
+ $output['errors'][] = $snapshotquery->get_error_code() . ($snapshotquery->get_error_message() ? ' - ' . $snapshotquery->get_error_code() : '');
+
+ } else {
+
+ HeadwaySkinOption::set('last-snapshot', time());
+
+ return array(
+ 'id' => $wpdb->insert_id,
+ 'comments' => $insert_args['comments'],
+ 'timestamp' => $insert_args['timestamp']
+ );
+
+ }
+
+ }
+
+
+ public static function rollback($rollback_id) {
+
+ global $wpdb;
+
+ if ( !$rollback = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->hw_snapshots WHERE id = %d AND template = '%s'", $rollback_id, HeadwayOption::$current_skin), ARRAY_A) )
+ return array('errors' => array('Snapshot does not exist.'));
+
+ $rollback_process = self::process_rollback($rollback);
+
+ return !is_wp_error($rollback_process) ? true : $rollback_process;
+
+ }
+
+
+ public static function process_rollback($data, $template = false) {
+
+ global $wpdb;
+
+ if ( !$template )
+ $template = HeadwayOption::$current_skin;
+
+ $data_arrays = array(
+ 'data_wp_options',
+ 'data_wp_postmeta',
+ 'data_hw_layout_meta',
+ 'data_hw_wrappers',
+ 'data_hw_blocks'
+ );
+
+ /* Go through data and delete and insert */
+ foreach ( $data_arrays as $data_array_id ) {
+
+ $data_set = headway_maybe_unserialize(headway_get($data_array_id, $data));
+ $table_name = str_replace(array('data_', 'wp_'), '', $data_array_id);
+ $wpdb_table_name = $wpdb->{$table_name};
+
+ /* Handle Headway tables */
+ if ( strpos($table_name, 'hw_') === 0 ) {
+
+ $delete_query = $wpdb->query($wpdb->prepare("DELETE FROM $wpdb_table_name WHERE template = '%s'", $template));
+
+ foreach ( $data_set as $data_object ) {
+
+ $insert_data = is_object($data_object) ? get_object_vars($data_object) : $data_object;
+ $insert_data['template'] = $template;
+
+ foreach ( $insert_data as $insert_data_key => $insert_data_value ) {
+
+ if ( is_array($insert_data_value) ) {
+ $insert_data[$insert_data_key] = headway_maybe_serialize($insert_data_value);
+ }
+
+ }
+
+ $insert_query = $wpdb->insert($wpdb_table_name, $insert_data);
+
+ }
+
+ /* Handle WP options/postmeta */
+ } else if ( $table_name == 'options' || $table_name == 'postmeta' ) {
+
+ $prefix = $table_name == 'options' ? 'headway_|template=' . $template . '|_' : '_hw_|template=' . $template . '|_';
+ $key_column = $table_name == 'options' ? 'option_name' : 'meta_key';
+
+ $delete_query = $wpdb->query($wpdb->prepare("DELETE FROM $wpdb_table_name WHERE $key_column LIKE '%s'", $prefix . '%'));
+
+ foreach ( $data_set as $data_object ) {
+
+ $insert_data = is_object($data_object) ? get_object_vars($data_object) : $data_object;
+
+ if ( isset($insert_data['option_id']) )
+ unset($insert_data['option_id']);
+
+ if ( isset($insert_data['meta_id']) )
+ unset($insert_data['meta_id']);
+
+ /* Build the key column ID with the correct template */
+ $key_column_fragments = explode('|_', $insert_data[$key_column]);
+ $key_column_id_without_prefix = $key_column_fragments[1];
+
+ $insert_data[$key_column] = $prefix . $key_column_id_without_prefix;
+
+ /* Fix wrapper IDs */
+ if ( strpos($key_column_id_without_prefix, 'option_group_design') !== false ) {
+ $insert_data['option_value'] = headway_preg_replace_json( "/-layout-[\w-]*/", '', $insert_data['option_value'] );
+ }
+
+ foreach ( $insert_data as $insert_data_key => $insert_data_value ) {
+
+ if ( is_array($insert_data_value) ) {
+ $insert_data[$insert_data_key] = headway_maybe_serialize($insert_data_value);
+ }
+
+ }
+
+ $insert_query = $wpdb->insert($wpdb_table_name, $insert_data);
+
+ }
+
+ }
+
+ }
+
+ do_action('headway_snapshot_rollback');
+
+ return $data;
+
+ }
+
+
+ public static function delete($id) {
+
+ global $wpdb;
+
+ return $wpdb->delete( $wpdb->hw_snapshots, array(
+ 'id' => $id,
+ 'template' => HeadwayOption::$current_skin
+ ) );
+
+ }
+
+
+ public static function delete_by_template($template) {
+
+ global $wpdb;
+
+ return $wpdb->delete($wpdb->hw_snapshots, array(
+ 'template' => $template
+ ));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/data/data-wrappers.php b/wp-content/themes/headway/library/data/data-wrappers.php
new file mode 100644
index 0000000..d7b00c1
--- /dev/null
+++ b/wp-content/themes/headway/library/data/data-wrappers.php
@@ -0,0 +1,390 @@
+ uniqid('w' . strtolower(substr($random_prefix, 0, 2))),
+ 'template' => headway_get('template', $args, HeadwayOption::$current_skin),
+ 'layout' => $layout_id,
+ 'position' => $args['position'],
+ 'settings' => headway_maybe_serialize(headway_get('settings', $args, array())),
+ 'mirror_id' => $mirror_id
+ );
+
+ if ( $insert_id = headway_get('insert_id', $args) )
+ $insert_args['id'] = $insert_id;
+
+ if ( $legacy_id = headway_get('legacy_id', $args) )
+ $insert_args['legacy_id'] = $legacy_id;
+
+ //Run the query
+ $wpdb->insert($wpdb->hw_wrappers, $insert_args);
+
+ //All done. Spit back ID of newly created wrapper.
+ return $insert_args['id'];
+
+ }
+
+
+ public static function update_wrapper($wrapper_id, $args) {
+
+ global $wpdb;
+
+ $wrapper_to_be_updated = self::get_wrapper($wrapper_id);
+
+ /* Make sure wrapper exists */
+ if ( !$wrapper_to_be_updated )
+ return null;
+
+ /* Map mirror-wrapper setting to mirror_id column */
+ if ( isset($args['settings']) && isset($args['settings']['mirror-wrapper']) ) {
+
+ $args['mirror_id'] = $args['settings']['mirror-wrapper'];
+ unset($args['settings']['mirror-wrapper']);
+
+ }
+
+ /* Handle template argument */
+ $template = headway_get('template', $args, HeadwayOption::$current_skin);
+
+ if ( isset($args['template']) )
+ unset($args['template']);
+
+ /* Query */
+ $query = $wpdb->update($wpdb->hw_wrappers, array_map('headway_maybe_serialize', $args), array(
+ 'template' => $template,
+ 'id' => $wrapper_id
+ ));
+
+ return $query;
+
+ }
+
+
+ /**
+ * @todo remove design instances and remove blocks in that wrapper here
+ * @param $wrapper_id
+ *
+ * @return null
+ */
+ public static function delete_wrapper($layout_id, $wrapper_id) {
+
+ global $wpdb;
+
+ $wrapper_to_be_deleted = self::get_wrapper($wrapper_id);
+
+ /* Make sure wrapper exists */
+ if ( !$wrapper_to_be_deleted )
+ return null;
+
+ /* Query for deletion */
+ $wrapper_delete_query = $wpdb->delete( $wpdb->hw_wrappers, array(
+ 'template' => HeadwayOption::$current_skin,
+ 'id' => $wrapper_id
+ ));
+
+ /* Delete design settings */
+ self::delete_wrapper_design_instances($layout_id, $wrapper_id);
+
+ /* Unmirror the wrappers mirroring this wrappers */
+ $wpdb->update( $wpdb->hw_wrappers, array(
+ 'mirror_id' => ''
+ ), array(
+ 'mirror_id' => $wrapper_id
+ ));
+
+ /* Delete all blocks in that wrapper */
+ $blocks_delete_query = HeadwayBlocksData::delete_by_wrapper($layout_id, $wrapper_id);
+
+ return array($wrapper_delete_query, $blocks_delete_query);
+
+ }
+
+
+ public static function delete_wrapper_design_instances($layout_id, $wrapper_id) {
+
+ return HeadwayElementsData::delete_special_element_properties(null, 'wrapper', 'instance', 'wrapper-' . HeadwayWrappers::format_wrapper_id($wrapper_id));
+
+ }
+
+
+ public static function delete_by_layout($layout_id) {
+
+ global $wpdb;
+
+ $layout_wrappers = self::get_wrappers_by_layout($layout_id);
+ $return = array();
+
+ foreach ( $layout_wrappers as $wrapper_id => $options ) {
+ $return[$wrapper_id] = self::delete_wrapper($layout_id, $wrapper_id);
+ }
+
+ return $return;
+
+ }
+
+
+ public static function delete_by_template($template) {
+
+ global $wpdb;
+
+ return $wpdb->delete( $wpdb->hw_wrappers, array(
+ 'template' => $template
+ ));
+
+ }
+
+
+ public static function get_wrapper($wrapper, $use_mirrored = false) {
+
+ global $wpdb;
+
+ /* If $wrapper is already an array then validate it and return it */
+ if ( is_array($wrapper) ) {
+
+ if ( isset($wrapper['id']) ) {
+ return $wrapper;
+ } else {
+ return null;
+ }
+
+ }
+
+ /* Build cache key */
+ $cache_key = 'hw_wrapper_' . $wrapper;
+
+ if ( $use_mirrored )
+ $cache_key .= '_using_mirrored';
+
+ /* Check cache */
+ $wrapper_from_cache = wp_cache_get($cache_key);
+
+ if ( $wrapper_from_cache !== false )
+ return $wrapper_from_cache;
+
+ /* Not cached... Retrieve wrapper */
+ if ( is_string($wrapper) || is_numeric($wrapper) ) {
+
+ $wrapper_id = HeadwayWrappers::format_wrapper_id($wrapper);
+
+ $wrapper_query = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->hw_wrappers WHERE template = '%s' AND id = '%s'", HeadwayOption::$current_skin, $wrapper_id), ARRAY_A);
+
+ if ( is_array($wrapper_query) && !is_wp_error($wrapper_query) ) {
+
+ $wrapper = array_map('headway_maybe_unserialize', $wrapper_query);
+
+ } else {
+
+ /* If no wrapper is found, try querying the legacy_id */
+ $wrapper_from_legacy_id = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->hw_wrappers WHERE template = '%s' AND legacy_id = '%d'", HeadwayOption::$current_skin, $wrapper_id), ARRAY_A);
+
+ if ( is_array($wrapper_from_legacy_id) && ! is_wp_error( $wrapper_from_legacy_id ) ) {
+ $wrapper = array_map( 'headway_maybe_unserialize', $wrapper_from_legacy_id );
+ } else {
+ $wrapper = null;
+ }
+
+ }
+
+ }
+
+ if ( is_array($wrapper) && !isset($wrapper['id']) )
+ return null;
+
+ /* Fetch the mirrored wrapper if $use_mirrored is true */
+ if ( $use_mirrored === true && $mirrored_wrapper = self::get_wrapper_mirror($wrapper) )
+ $wrapper = $mirrored_wrapper;
+
+ wp_cache_set($cache_key, $wrapper);
+
+ return $wrapper;
+
+ }
+
+
+ public static function get_wrappers_by_layout($layout_id, $include_styling = false) {
+
+ global $wpdb;
+
+ /* Build cache key */
+ $cache_key = 'hw_wrappers_by_layout_' . $layout_id;
+
+ if ( $include_styling )
+ $cache_key = $cache_key . '_with_styling';
+
+ /* Check cache */
+ $layout_wrappers = wp_cache_get($cache_key);
+
+ if ( $layout_wrappers === false ) {
+
+ /* Retrieve all wrappers from layout */
+ $layout_wrappers_query = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->hw_wrappers WHERE template = '%s' AND layout = '%s' ORDER BY position ASC", HeadwayOption::$current_skin, $layout_id), ARRAY_A);
+
+ /* Change results array into associative */
+ $layout_wrappers = array();
+
+ foreach ( $layout_wrappers_query as $layout_wrapper ) {
+ $layout_wrappers[$layout_wrapper['id']] = array_map('headway_maybe_unserialize', $layout_wrapper);
+ }
+
+ /* If wrapper array is empty then load the default wrapper array */
+ if ( !count($layout_wrappers) ) {
+ $layout_wrappers = HeadwayWrappers::$default_wrappers;
+ $layout_wrappers['default']['layout'] = $layout_id;
+ }
+
+ if ( $include_styling ) {
+ $layout_wrappers = self::add_wrapper_styling_to_array($layout_wrappers);
+ }
+
+ wp_cache_set($cache_key, $layout_wrappers);
+
+ }
+
+ return $layout_wrappers;
+
+ }
+
+
+ public static function get_all_wrappers($include_styling = false, $mirrored_only = false) {
+
+ global $wpdb;
+
+ /* Build cache key */
+ $cache_key = 'hw_all_wrappers';
+
+ if ( $include_styling )
+ $cache_key .= '_with_styling';
+
+ if ( $mirrored_only )
+ $cache_key .= '_mirrored_only';
+
+ /* Check cache */
+ $wrappers_from_cache = wp_cache_get($cache_key);
+
+ if ( $wrappers_from_cache !== false )
+ return $wrappers_from_cache;
+
+ /* Not cached... Retrieve all wrappers */
+ $query = "SELECT * FROM $wpdb->hw_wrappers WHERE template = '%s'";
+
+ if ( $mirrored_only )
+ $query .= " AND mirror_id <> ''";
+
+ $wrapper_query = $wpdb->get_results($wpdb->prepare($query, HeadwayOption::$current_skin), ARRAY_A);
+
+ /* Change results array into associative */
+ $wrappers = array();
+
+ foreach ( $wrapper_query as $wrapper ) {
+ $wrappers[$wrapper['id']] = array_map('headway_maybe_unserialize', $wrapper);
+ }
+
+ if ( $include_styling ) {
+ $wrappers = self::add_wrapper_styling_to_array($wrappers);
+ }
+
+ wp_cache_set($cache_key, $wrappers);
+
+ return $wrappers;
+
+ }
+
+
+ public static function add_wrapper_styling_to_array($wrappers) {
+
+ if ( !is_array($wrappers) )
+ return false;
+
+ /* If the array provided is just one wrapper, then put it into an array */
+ if ( isset($wrappers['id']) && isset($wrappers['position']) ) {
+ $wrappers = array($wrappers);
+ }
+
+ foreach ( $wrappers as $wrapper_id => $wrapper ) {
+
+ $wrappers[$wrapper_id]['styling'] = HeadwayElementsData::get_special_element_properties(array(
+ 'element' => 'wrapper',
+ 'se_type' => 'instance',
+ 'se_meta' => 'wrapper-' . HeadwayWrappers::format_wrapper_id($wrapper_id)
+ ));
+
+ }
+
+ return $wrappers;
+
+ }
+
+
+ public static function is_wrapper_mirrored($wrapper) {
+
+ $wrapper = self::get_wrapper($wrapper);
+
+ if ( $mirrored_wrapper_id = headway_get('mirror_id', $wrapper) )
+ return $mirrored_wrapper_id;
+
+ return false;
+
+ }
+
+
+ public static function get_wrapper_mirror($wrapper) {
+
+ $wrapper = self::get_wrapper($wrapper);
+
+ if ( $mirrored_wrapper_id = headway_get('mirror_id', $wrapper) )
+ return self::get_wrapper($mirrored_wrapper_id);
+
+ return false;
+
+ }
+
+
+ public static function wrapper_exists($id) {
+
+ if ( self::get_wrapper($id) )
+ return true;
+
+ return false;
+
+ }
+
+ public static function get_wrapper_setting($wrapper, $option_name, $default_value = null) {
+
+ if (!is_array($wrapper))
+ $wrapper = HeadwayWrappersData::get_wrapper($wrapper);
+
+ return headway_get($option_name, headway_get('settings', $wrapper, array()), $default_value);
+
+ }
+
+
+ public static function get_legacy_id( $wrapper ) {
+
+ return is_numeric( headway_get( 'legacy_id', $wrapper ) ) && headway_get( 'legacy_id', $wrapper ) > 0 ? headway_get( 'legacy_id', $wrapper ) : $wrapper['id'];
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/defaults/default-design-settings.php b/wp-content/themes/headway/library/defaults/default-design-settings.php
new file mode 100644
index 0000000..b443fa4
--- /dev/null
+++ b/wp-content/themes/headway/library/defaults/default-design-settings.php
@@ -0,0 +1,585 @@
+ array(
+ 'properties' => array(
+ 'font-size' => '14',
+ 'font-family' => 'palatino',
+ 'line-height' => '100',
+ 'color' => '555555'
+ )
+ ),
+
+ 'default-hyperlink' => array(
+ 'properties' => array(
+ 'color' => '555555'
+ )
+ ),
+
+ 'default-blockquote' => array(
+ 'properties' => array(
+ 'color' => '666666',
+ 'padding-top' => '5',
+ 'padding-right' => '0',
+ 'padding-bottom' => '5',
+ 'padding-left' => '25',
+ 'border-left-width' => '2',
+ 'border-style' => 'solid',
+ 'border-color' => '666666',
+ 'margin-top' => '15',
+ 'margin-right' => '0',
+ 'margin-bottom' => '15',
+ 'margin-left' => '20'
+
+ )
+ ),
+
+ 'default-block' => array(
+ 'properties' => array(
+ 'overflow' => 'hidden',
+ 'margin-bottom' => '10'
+ )
+ ),
+
+ 'block-title' => array(
+ 'properties' => array(
+ 'font-size' => '22',
+ 'line-height' => '150'
+ )
+ ),
+
+ 'block-subtitle' => array(
+ 'properties' => array(
+ 'font-size' => '14',
+ 'font-styling' => 'italic',
+ 'color' => '999999'
+ )
+ ),
+
+ /* Structure */
+ 'body' => array(
+ 'properties' => array(
+ 'background-color' => 'dddddd'
+ )
+ ),
+
+ 'wrapper' => array(
+ 'properties' => array(
+ 'background-color' => 'ffffff',
+ 'padding-top' => '15',
+ 'padding-right' => '15',
+ 'padding-bottom' => '15',
+ 'padding-left' => '15',
+ 'box-shadow-color' => 'c7c7c7',
+ 'box-shadow-blur' => '8',
+ 'box-shadow-horizontal-offset' => '1',
+ 'box-shadow-vertical-offset' => '1',
+ 'margin-top' => '30',
+ 'margin-bottom' => '30'
+ )
+ ),
+
+ /* Header Block */
+ 'block-header-site-title' => array(
+ 'properties' => array(
+ 'color' => '222222',
+ 'font-size' => '34',
+ 'line-height' => '100',
+ 'text-decoration' => 'none',
+ 'margin-top' => '20',
+ 'margin-right' => '10',
+ 'margin-bottom' => '0',
+ 'margin-left' => '10'
+ )
+ ),
+
+ 'block-header-site-tagline' => array(
+ 'properties' => array(
+ 'color' => '999999',
+ 'font-size' => '15',
+ 'line-height' => '120',
+ 'font-styling' => 'italic',
+ 'margin-top' => '10',
+ 'margin-right' => '10',
+ 'margin-bottom' => '20',
+ 'margin-left' => '10'
+ )
+ ),
+
+ /* Navigation Block */
+ 'block-navigation' => array(
+ 'properties' => array(
+ 'border-top-width' => '1',
+ 'border-bottom-width' => '1',
+ 'border-left-width' => '0',
+ 'border-right-width' => '0',
+ 'border-color' => 'eeeeee',
+ 'border-style' => 'solid',
+ 'overflow' => 'visible'
+ )
+ ),
+
+ 'block-navigation-menu-item' => array(
+ 'properties' => array(
+ 'text-decoration' => 'none',
+ 'color' => '888888',
+ 'capitalization' => 'uppercase',
+ 'padding-right' => '15',
+ 'padding-left' => '15'
+ ),
+ 'special-element-state' => array(
+ 'selected' => array(
+ 'color' => '222222'
+ ),
+ 'hover' => array(
+ 'color' => '555555'
+ )
+ )
+ ),
+
+ 'block-navigation-sub-nav-menu' => array(
+ 'properties' => array(
+ 'background-color' => 'eeeeee'
+ )
+ ),
+
+ /* Widget Block */
+ 'block-widget-area-widget' => array(
+ 'properties' => array(
+ 'line-height' => '150',
+ 'padding-top' => '5',
+ 'padding-right' => '10',
+ 'padding-bottom' => '5',
+ 'padding-left' => '10',
+ 'margin-top' => '15'
+ )
+ ),
+
+ 'block-widget-area-widget-title' => array(
+ 'properties' => array(
+ 'font-size' => '13',
+ 'border-style' => 'solid',
+ 'border-top-width' => '1',
+ 'border-bottom-width' => '1',
+ 'border-left-width' => '0',
+ 'border-right-width' => '0',
+ 'border-color' => 'eeeeee',
+ 'letter-spacing' => '1',
+ 'capitalization' => 'uppercase',
+ 'line-height' => '250',
+ 'color' => '111111',
+ 'margin-bottom' => '10'
+ )
+ ),
+
+ 'block-widget-area-widget-links' => array(
+ 'properties' => array(
+ 'color' => '333333'
+ )
+ ),
+
+ /* Content Block */
+ 'block-content-entry-container' => array(
+ 'properties' => array(
+ 'border-style' => 'solid',
+ 'border-top-width' => '0',
+ 'border-bottom-width' => '1',
+ 'border-left-width' => '0',
+ 'border-right-width' => '0',
+ 'border-color' => 'efefef',
+ 'padding-bottom' => '30'
+ )
+ ),
+
+ 'block-content-title' => array(
+ 'properties' => array(
+ 'font-size' => '24',
+ 'color' => '333333',
+ 'line-height' => '130'
+ )
+ ),
+
+ 'block-content-archive-title' => array(
+ 'properties' => array(
+ 'font-size' => '24',
+ 'color' => '555555',
+ 'line-height' => '110',
+ 'border-bottom-width' => '1',
+ 'border-color' => 'eeeeee',
+ 'border-style' => 'solid',
+ 'padding-bottom' => '15'
+ )
+ ),
+
+ 'block-content-entry-meta' => array(
+ 'properties' => array(
+ 'line-height' => '120',
+ 'color' => '818181'
+ )
+ ),
+
+ 'block-content-entry-content' => array(
+ 'properties' => array(
+ 'color' => '555555',
+ 'font-size' => '14',
+ 'line-height' => '180'
+ )
+ ),
+
+ 'block-content-heading' => array(
+ 'properties' => array(
+ 'font-size' => '20',
+ 'line-height' => '180'
+ )
+ ),
+
+ 'block-content-sub-heading' => array(
+ 'properties' => array(
+ 'font-size' => '16',
+ 'line-height' => '180'
+ )
+ ),
+
+ 'block-content-more-link' => array(
+ 'properties' => array(
+ 'background-color' => 'eeeeee',
+ 'text-decoration' => 'none',
+ 'border-top-left-radius' => '4',
+ 'border-top-right-radius' => '4',
+ 'border-bottom-right-radius' => '4',
+ 'border-bottom-left-radius' => '4',
+ 'padding-top' => '2',
+ 'padding-right' => '6',
+ 'padding-bottom' => '2',
+ 'padding-left' => '6'
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'background-color' => 'e7e7e7'
+ )
+ )
+ ),
+
+ 'block-content-loop-navigation-link' => array(
+ 'properties' => array(
+ 'background-color' => 'e1e1e1',
+ 'text-decoration' => 'none',
+ 'border-top-left-radius' => '4',
+ 'border-top-right-radius' => '4',
+ 'border-bottom-right-radius' => '4',
+ 'border-bottom-left-radius' => '4',
+ 'padding-top' => '4',
+ 'padding-right' => '8',
+ 'padding-bottom' => '4',
+ 'padding-left' => '8',
+ 'line-height' => '130'
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'background-color' => 'd5d5d5'
+ )
+ )
+ ),
+
+ 'block-content-post-thumbnail' => array(
+ 'properties' => array(
+ 'border-top-width' => '1',
+ 'border-right-width' => '1',
+ 'border-bottom-width' => '1',
+ 'border-left-width' => '1',
+ 'border-color' => 'eeeeee',
+ 'border-style' => 'solid',
+ 'padding-top' => '3',
+ 'padding-right' => '3',
+ 'padding-bottom' => '3',
+ 'padding-left' => '3'
+ )
+ ),
+
+ 'block-content-comments-area-headings' => array(
+ 'properties' => array(
+ 'color' => '333333',
+ 'font-size' => '18',
+ 'line-height' => '130'
+ )
+ ),
+
+ 'block-content-comment-container' => array(
+ 'properties' => array(
+ 'padding-left' => '64'
+ )
+ ),
+
+ 'block-content-comment-author' => array(
+ 'properties' => array(
+ 'font-size' => '18',
+ 'line-height' => '120'
+ )
+ ),
+
+ 'block-content-comment-meta' => array(
+ 'properties' => array(
+ 'color' => '888888',
+ 'font-size' => '14'
+ )
+ ),
+
+ 'block-content-comment-body' => array(
+ 'properties' => array(
+ 'font-size' => '14',
+ 'line-height' => '170'
+ )
+ ),
+
+ 'block-content-comment-reply-link' => array(
+ 'properties' => array(
+ 'font-size' => '12',
+ 'background-color' => 'eeeeee',
+ 'text-decoration' => 'none',
+ 'border-top-left-radius' => '4',
+ 'border-top-right-radius' => '4',
+ 'border-bottom-right-radius' => '4',
+ 'border-bottom-left-radius' => '4',
+ 'padding-top' => '3',
+ 'padding-right' => '6',
+ 'padding-bottom' => '3',
+ 'padding-left' => '6'
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'background-color' => 'e7e7e7'
+ )
+ )
+ ),
+
+ 'block-content-comment-form-input-label' => array(
+ 'properties' => array(
+ 'font-size' => '14',
+ 'line-height' => '220',
+ 'color' => '888888'
+ )
+ ),
+
+
+ /* Slider */
+ 'block-slider-slider-container' => array(
+ 'properties' => array(
+ 'overflow' => 'visible',
+ 'margin-bottom' => '30'
+ )
+ ),
+
+ 'block-slider-slider-viewport' => array(
+ 'properties' => array(
+ 'overflow' => 'hidden'
+ )
+ ),
+
+ 'block-slider-slider-caption' => array(
+ 'properties' => array(
+ 'background-color' => 'rgba(0, 0, 0, 0.6)',
+ 'color' => 'ffffff',
+ 'font-size' => '14',
+ 'line-height' => '150',
+ 'padding-top' => '20',
+ 'padding-right' => '20',
+ 'padding-bottom' => '20',
+ 'padding-left' => '20',
+ 'position' => 'absolute',
+ 'text-align' =>'center'
+ )
+ ),
+
+ 'block-slider-slider-paging' => array(
+ 'properties' => array(
+ 'position' => 'absolute',
+ 'text-align' => 'center'
+ )
+ ),
+
+ 'block-slider-slider-direction-nav-link' => array(
+ 'properties' => array(
+ 'margin-top' => '-20',
+ 'position' => 'absolute',
+ 'background-image' => headway_url() . '/library/blocks/slider/assets/bg_direction_nav.png',
+ 'background-repeat' => 'no-repeat',
+ 'background-position' => 'left top'
+ )
+ ),
+
+ 'block-slider-slider-direction-nav-next' => array(
+ 'properties' => array(
+ 'background-position' => 'right top'
+ )
+ ),
+
+ 'block-slider-slider-paging-link' => array(
+ 'properties' => array(
+ 'background-color' => 'rgba(0,0,0,0.5)',
+ 'border-top-left-radius' => '20',
+ 'border-top-right-radius' => '20',
+ 'border-bottom-right-radius' => '20',
+ 'border-bottom-left-radius' => '20',
+ 'margin-left' => '2',
+ 'margin-right' => '2'
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'background-color' => 'rgba(0,0,0,0.7)'
+ ),
+ 'active' => array(
+ 'background-color' => 'rgba(0,0,0,0.9)'
+ )
+ )
+ ),
+
+
+ /* Text Block */
+ 'block-text-heading' => array(
+ 'properties' => array(
+ 'font-size' => '20',
+ 'line-height' => '180'
+ )
+ ),
+
+ 'block-text-sub-heading' => array(
+ 'properties' => array(
+ 'font-size' => '16',
+ 'line-height' => '180'
+ )
+ ),
+ /* End Text Block */
+
+
+ /* Pin Board */
+ 'block-pin-board-pin' => array(
+ 'properties' => array(
+ 'padding-top' => 1,
+ 'padding-right' => 1,
+ 'padding-bottom' => 1,
+ 'padding-left' => 1,
+
+ 'background-color' => 'ffffff',
+
+ 'border-color' => 'eeeeee',
+ 'border-style' => 'solid',
+ 'border-top-width' => 1,
+ 'border-right-width' => 1,
+ 'border-bottom-width' => 1,
+ 'border-left-width' => 1,
+
+ 'box-shadow-color' => 'eee',
+ 'box-shadow-blur' => 3,
+ 'box-shadow-horizontal-offset' => 0,
+ 'box-shadow-vertical-offset' => 2
+ )
+ ),
+
+ 'block-pin-board-pin-title' => array(
+ 'properties' => array(
+ 'padding-top' => 15,
+ 'padding-right' => 15,
+ 'padding-left' => 15,
+
+ 'font-size' => 18,
+ 'line-height' => 120,
+
+ 'text-decoration' => 'none'
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'text-decoration' => 'underline'
+ )
+ )
+ ),
+
+ 'block-pin-board-pin-text' => array(
+ 'properties' => array(
+ 'font-size' => 12,
+ 'line-height' => 150,
+
+ 'padding-right' => 15,
+ 'padding-left' => 15
+ )
+ ),
+
+ 'block-pin-board-pin-meta' => array(
+ 'properties' => array(
+ 'font-size' => 12,
+ 'line-height' => 120,
+
+ 'padding-right' => 15,
+ 'padding-left' => 15,
+
+ 'color' => '888888'
+ )
+ ),
+
+ 'block-pin-board-pagination-button' => array(
+ 'properties' => array(
+ 'text-decoration' => 'none',
+ 'background-color' => 'eeeeee',
+
+ 'border-top-left-radius' => 4,
+ 'border-top-right-radius' => 4,
+ 'border-bottom-right-radius' => 4,
+ 'border-bottom-left-radius' => 4,
+
+ 'padding-top' => 5,
+ 'padding-right' => 9,
+ 'padding-bottom' => 5,
+ 'padding-left' => 9
+ ),
+ 'special-element-state' => array(
+ 'hover' => array(
+ 'background-color' => 'e7e7e7'
+ )
+ )
+ ),
+ /* End Pin Board */
+
+
+ /* Footer */
+ 'block-footer' => array(
+ 'properties' => array(
+ 'border-top-width' => '1',
+ 'border-right-width' => '0',
+ 'border-bottom-width' => '0',
+ 'border-left-width' => '0',
+ 'border-color' => 'eeeeee',
+ 'border-style' => 'solid'
+ )
+ ),
+
+ 'block-footer-copyright' => array(
+ 'properties' => array(
+ 'color' => '666666'
+ )
+ ),
+
+ 'block-footer-headway-attribution' => array(
+ 'properties' => array(
+ 'color' => '666666'
+ )
+ ),
+
+ 'block-footer-administration-panel' => array(
+ 'properties' => array(
+ 'color' => '666666'
+ )
+ ),
+
+ 'block-footer-go-to-top' => array(
+ 'properties' => array(
+ 'color' => '666666'
+ )
+ ),
+
+ 'block-footer-responsive-grid-link' => array(
+ 'properties' => array(
+ 'color' => '666666'
+ )
+ )
+);
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/display/display.php b/wp-content/themes/headway/library/display/display.php
new file mode 100644
index 0000000..902ea2c
--- /dev/null
+++ b/wp-content/themes/headway/library/display/display.php
@@ -0,0 +1,288 @@
+ true,
+ 'display/grid-renderer',
+ 'display/layout-renderer'
+ ));
+
+ add_filter('body_class', array(__CLASS__, 'body_class'));
+
+ if ( HeadwayRoute::is_visual_editor_iframe() ) {
+
+ Headway::load('visual-editor', 'VisualEditor');
+
+ HeadwayAdminBar::remove_admin_bar();
+
+ }
+
+ /* If it's a plugin template, then route all of the content to the content block */
+ add_action('get_header', array(__CLASS__, 'handle_plugin_template'), 1);
+
+ }
+
+
+ public static function layout() {
+
+ get_header();
+
+ self::grid();
+
+ get_footer();
+
+ }
+
+
+ public static function grid() {
+
+ echo "\n\n";
+
+ if ( current_theme_supports('headway-grid') ) {
+
+ $layout = new HeadwayLayoutRenderer;
+ $layout->display();
+
+ } else {
+
+ echo '
The Headway Grid is not supported in this Child Theme.
+ ' . $font['name'] . '
+ The quick brown fox jumps over the lazy dog.
+
+
+
+
+ ';
+
+ }
+
+ return true;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/fonts/web-fonts-loader.php b/wp-content/themes/headway/library/fonts/web-fonts-loader.php
new file mode 100644
index 0000000..cd51761
--- /dev/null
+++ b/wp-content/themes/headway/library/fonts/web-fonts-loader.php
@@ -0,0 +1,125 @@
+ $font )
+ $webfonts_in_use['google'][ $key ] = urlencode( $font );
+
+ $stylesheet_url = '//fonts.googleapis.com/css?family=' . implode( '|', $webfonts_in_use['google'] );
+
+ echo "\n";
+
+ }
+ /* End Google Web Fonts */
+
+
+ public static function get_fonts_in_use() {
+
+ /* If cache exists then use it */
+ $cache = get_transient( 'hw_webfont_cache_template_' . HeadwayOption::$current_skin );
+
+ if ( is_array($cache) )
+ return $cache;
+
+ /* Build cache otherwise */
+ self::cache();
+
+ return get_transient( 'hw_webfont_cache_template_' . HeadwayOption::$current_skin );
+
+ }
+
+
+ public static function cache() {
+
+ $raw_webfonts = self::pluck_webfonts(HeadwayElementsData::get_all_elements());
+ $sorted_webfonts = array();
+
+ foreach ( $raw_webfonts as $webfont ) {
+
+ $fragments = explode('|', $webfont);
+
+ $sorted_webfonts[$fragments[0]][] = !empty($fragments[2]) ? $fragments[1] . ':' . $fragments[2] : $fragments[1]; /* $fragments[2] are the variants */
+ $sorted_webfonts[$fragments[0]] = array_unique($sorted_webfonts[$fragments[0]]);
+
+ }
+
+ return set_transient( 'hw_webfont_cache_template_' . HeadwayOption::$current_skin, $sorted_webfonts );
+
+ }
+
+
+ public static function pluck_webfonts($array) {
+
+ $web_fonts = array();
+
+ foreach ( $array as $key => $value ) {
+
+ /* If the value is an array, then loop this function to pluck the font values out of instances, states, etc */
+ if ( is_array($value) ) {
+
+ $web_fonts = array_merge($web_fonts, self::pluck_webfonts($value));
+
+ /* We've found a font family property. Now make sure that the font is a web font by checking for the | delimiter */
+ } else if ( $key === 'font-family' && strpos($value, '|') ) {
+
+ $web_fonts[] = $value;
+
+ }
+
+ }
+
+ return array_unique($web_fonts);
+
+ }
+
+
+ public static function flush_cache() {
+
+ return delete_transient( 'hw_webfont_cache_template_' . HeadwayOption::$current_skin );
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/languages/da_DK.mo b/wp-content/themes/headway/library/languages/da_DK.mo
new file mode 100644
index 0000000..59b2f0e
Binary files /dev/null and b/wp-content/themes/headway/library/languages/da_DK.mo differ
diff --git a/wp-content/themes/headway/library/languages/da_DK.po b/wp-content/themes/headway/library/languages/da_DK.po
new file mode 100644
index 0000000..0e31854
--- /dev/null
+++ b/wp-content/themes/headway/library/languages/da_DK.po
@@ -0,0 +1,520 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Headway Base v3.4.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2013-04-04 11:42+0100\n"
+"Last-Translator: Mikkel Breum \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: CSL v1.x\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
+"_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
+"X-Poedit-Basepath: ../../\n"
+"X-Textdomain-Support: yes\n"
+"Language: da_DK\n"
+"X-Poedit-SearchPath-0: .\n"
+
+# @ headway
+#: library/admin/admin.php:353
+#, php-format
+msgid ""
+"
Remember!"
+"h3>
Please backup before updating. Headway Themes recommends BackupBuddy for all backup and "
+"migration needs.
"
+msgstr ""
+"
Husk!"
+"h3>
Tag en backup før du opdaterer. Headway Themes anbefaler BackupBuddy når du skal tage "
+"backup eller flytte server.
"
+
+# @ headway
+#: library/api/api-admin-meta-box.php:12
+msgid "Error: The meta box class being registered does not exist."
+msgstr "Fejl: Meta box klassen kan ikke registreres, da den ikke findes."
+
+# @ headway
+#: library/api/api-block.php:127
+msgid "Error: The block options class being registered does not exist."
+msgstr "Fejl: Block options klassen kan ikke registreres, da den ikke findes."
+
+# @ headway
+#: library/api/api-box.php:12
+msgid "Error: The box class being registered does not exist."
+msgstr "Fejl: Box klassen kan ikke registreres, da den ikke findes."
+
+# @ headway
+#: library/api/api-element.php:125
+msgid "Error: Arguments must be an array for this element."
+msgstr "Fejl: Argumenterne for dette element skal være et Array."
+
+# @ headway
+#: library/api/api-element.php:150
+msgid "Error: An ID is required for this element."
+msgstr "Fejl: Et ID er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:153
+msgid "Error: A name is required for this element."
+msgstr "Fejl: Et navn er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:156
+msgid "Error: A group is required for this element."
+msgstr "Fejl: En gruppe er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:159
+msgid "Error: A CSS selector is required for this element."
+msgstr "Fejl: En CSS selector er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:162
+msgid "Error: Properties are required for this element."
+msgstr "Fejl: Egenskaber er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:201
+msgid "Error: Arguments must be an array for this element instance."
+msgstr "Fejl: Argumenterne for dette element skal være et Array."
+
+# @ headway
+#: library/api/api-element.php:217
+msgid "Error: An ID is required for this element instance."
+msgstr "Fejl: Et ID er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:220
+msgid "Error: A name is required for this element instance."
+msgstr "Fejl: Et navn er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:223
+msgid "Error: A group is required for this element instance."
+msgstr "Fejl: En gruppe er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:226
+msgid "Error: A parent element is required for this element instance."
+msgstr "Fejl: Et forældre-element er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:229
+msgid "Error: A CSS selector is required for this element instance."
+msgstr "Fejl: En CSS selector er krævet for dette element."
+
+# @ headway
+#: library/api/api-element.php:239
+msgid "Error: The element specified does not support instances."
+msgstr "Fejl: Det specificerede element understøtter ikke instantiering."
+
+# @ headway
+#: library/api/api-element.php:265
+msgid "Error: The group being registered already exists."
+msgstr "Fejl: Gruppen findes allerede."
+
+# @ headway
+#: library/api/api-element.php:281
+msgid "Error: Arguments must be an array for deregistering this element."
+msgstr ""
+"Fejl: Argumenterne for afregistrering af dette element skal være et array."
+
+# @ headway
+#: library/api/api-element.php:293
+msgid "Error: A group is required for deregistering this element."
+msgstr "Fejl: En gruppe er krævet for afregistrering af dette element."
+
+# @ headway
+#: library/api/api-element.php:296
+msgid "Error: An ID is required for deregistering this element."
+msgstr "Fejl: Et ID er krævet for afregistrering af dette element."
+
+# @ headway
+#: library/api/api-element.php:318
+msgid ""
+"Error: Arguments must be an array for deregistering this element instance."
+msgstr ""
+"Fejl: Argumenterne for afregistrering af dette element skal være et array."
+
+# @ headway
+#: library/api/api-element.php:331
+msgid "Error: A group is required for deregistering this element instance."
+msgstr "Fejl: En gruppe er krævet for afregistrering af dette element."
+
+# @ headway
+#: library/api/api-element.php:334
+msgid ""
+"Error: An instance ID is required for deregistering this element instance."
+msgstr "Fejl: Et ID er krævet for afregistrering af dette element."
+
+# @ headway
+#: library/api/api-element.php:337
+msgid "Error: An element is required for deregistering this element instance."
+msgstr "Fejl: Et element er krævet for afregistrering af dette element."
+
+# @ headway
+#: library/api/api-element.php:357
+msgid "Error: The group being deregistered does not exist."
+msgstr "Fejl: Gruppen kan ikke afregistreres, da den ikke findes."
+
+# @ headway
+#: library/api/api-panel.php:12
+msgid "Error: The panel class being registered does not exist."
+msgstr "Fejl: Panel klassen kan ikke registreres, da den ikke findes."
+
+# @ headway
+#: library/api/api-updater.php:168
+#, php-format
+msgid ""
+"
%s %s is now available, you're running %s! Go to the "
+"Headway Dashboard to download the "
+"latest version or learn more about the "
+"update.
"
+msgstr ""
+"
%s %s er nu tilgængelig, du kører %s! Gå til Headway Dashboard'et for at downloade den "
+"seneste versioneller find ud af mere om "
+"opdateringen.
%s %s is now available, you're running %s! Your "
+"Headway license has expired. Please visit the Headway "
+"Dashboard to renew your license so you can continue to receive updates."
+"div>"
+msgstr ""
+"
%s %s er nu tilgængelig, du kører %s! Din Headway "
+"licens er udløbet. Gå venligst til Headway Dashboard'et "
+"for at forny din licens så du fortsat kan modtage opdateringer.
"
+
+# @ headway
+#: library/fonts/traditional-fonts.php:127
+msgid ""
+"To register a font, the argument array must include an \"id\", \"stack\", "
+"and \"name\"."
+msgstr ""
+"For at registrere en font, skal argument array'et indeholde \"id\", \"stack"
+"\", og \"name\"."
+
+# @ headway
+#: library/visual-editor/panels/design/panel-default-elements.php:32
+msgid "Please select a default element to the left."
+msgstr "Vælg venligst et standard element til venstre."
+
+# @ headway
+#: library/visual-editor/panels/design/panel-editor.php:115
+msgid "Please select an element to the left."
+msgstr "Vælg venligst et element til venstre."
diff --git a/wp-content/themes/headway/library/languages/de_DE.mo b/wp-content/themes/headway/library/languages/de_DE.mo
new file mode 100644
index 0000000..c7097c9
Binary files /dev/null and b/wp-content/themes/headway/library/languages/de_DE.mo differ
diff --git a/wp-content/themes/headway/library/languages/de_DE.po b/wp-content/themes/headway/library/languages/de_DE.po
new file mode 100644
index 0000000..85e9bc1
--- /dev/null
+++ b/wp-content/themes/headway/library/languages/de_DE.po
@@ -0,0 +1,523 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Headway Base v3.7.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2014-07-13 00:14+0100\n"
+"Last-Translator: Carsten Dohmann \n"
+"Language-Team: www.headway-support-deutsch.de \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Poedit 1.6.6\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
+"_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
+"X-Poedit-Basepath: ../../\n"
+"X-Textdomain-Support: yes\n"
+"Language: de_DE\n"
+"X-Poedit-SearchPath-0: .\n"
+
+# @ headway
+#: library/admin/admin.php:145 library/admin/admin.php:182
+msgid "Please contact Headway Support if this error persists."
+msgstr ""
+"Bitte melden Sie sich beim Headway Support, falls der Fehler weiterhin "
+"erscheint."
+
+# @ headway
+#: library/admin/admin.php:169
+msgid "License saved and activated."
+msgstr "Lizenz gespeichert und aktiviert."
+
+# @ headway
+#: library/admin/admin.php:173
+msgid ""
+"\n"
+"\t\t\t\t\tWhoops! Could not activate license. Please check "
+"that you have entered your license correctly and that it has not expired."
+"
\n"
+"\n"
+"\\\t\\\t\\\t\\\t\\\tPrüfen Sie ob Sie Ihre Lizenz richtig kopiert haben vom "
+"Headway "
+"Dashboard.\n"
+"\n"
+"\\\t\\\t\\\t\\\t"
+
+# @ default
+#: library/admin/pages/options.php:49
+msgid "Deactivate License"
+msgstr "Lizenz deaktivieren."
+
+# @ default
+#: library/admin/pages/options.php:50
+msgid "Active"
+msgstr "Aktiv"
+
+# @ default
+#: library/admin/pages/options.php:52 library/admin/pages/options.php:55
+msgid "Save & Activate License"
+msgstr "Speichern & Lizenz aktivieren."
+
+# @ headway
+#: library/admin/pages/whats-new.php:2
+#, php-format
+msgid "Welcome to Headway %s"
+msgstr "Willkommen zu Headway %s"
+
+# @ headway
+#: library/admin/pages/whats-new.php:4
+msgid ""
+"Thank you for updating! Headway 3.7 has many improvements we think you'll "
+"enjoy."
+msgstr ""
+"Vielen Dank fürs aktualisieren! Headway 3.7 beinhaltet viele Verbesserungen, "
+"die Sie lieben werden."
+
+# @ headway
+#: library/api/api-admin-meta-box.php:12
+msgid "Error: The meta box class being registered does not exist."
+msgstr "Fehler: Die zu registrierende Meta Box Klasse existiert nicht."
+
+# @ headway
+#: library/api/api-block.php:134
+msgid "Error: The block options class being registered does not exist."
+msgstr "Fehler: Die zu registrierende Block Optionen Klasse existiert nicht."
+
+# @ headway
+#: library/api/api-box.php:12
+msgid "Error: The box class being registered does not exist."
+msgstr "Fehler: Die zu registrierende Box Klasse existiert nicht."
+
+# @ headway
+#: library/api/api-element.php:110
+msgid "Error: Arguments must be an array for this element."
+msgstr "Fehler: Argumente müssen in einem Array für dieses Element vorliegen."
+
+# @ headway
+#: library/api/api-element.php:134
+msgid "Error: An ID is required for this element."
+msgstr "Fehler: Eine ID muss für dieses Element vergeben werden."
+
+# @ headway
+#: library/api/api-element.php:137
+msgid "Error: A name is required for this element."
+msgstr "Fehler: Ein Name muss für dieses Element vergeben werden."
+
+# @ headway
+#: library/api/api-element.php:140
+msgid "Error: A group is required for this element."
+msgstr "Fehler: Eine Gruppe ist für dieses Element notwendig."
+
+# @ headway
+#: library/api/api-element.php:143
+msgid "Error: A CSS selector is required for this element."
+msgstr "Fehler: Eine CSS Auswahl (Selektor) ist für dieses Element notwendig."
+
+# @ headway
+#: library/api/api-element.php:146
+msgid "Error: Properties are required for this element."
+msgstr "Fehler: Einstellungen sind für dieses Element notwendig."
+
+# @ headway
+#: library/api/api-element.php:189
+msgid "Error: Arguments must be an array for this element instance."
+msgstr ""
+"Fehler: Argumente müssen in einem Array für diese Element-Instanz vorliegen."
+
+# @ headway
+#: library/api/api-element.php:205
+msgid "Error: An ID is required for this element instance."
+msgstr "Fehler: Eine ID muss für diese Element Instanz vorliegen."
+
+# @ headway
+#: library/api/api-element.php:208
+msgid "Error: A name is required for this element instance."
+msgstr "Fehler: Eine Name muss für diese Element Instanz vorliegen."
+
+# @ headway
+#: library/api/api-element.php:211
+msgid "Error: A group is required for this element instance."
+msgstr "Fehler: Eine Gruppe muss für diese Element Instanz vorliegen."
+
+# @ headway
+#: library/api/api-element.php:214
+msgid "Error: A parent element is required for this element instance."
+msgstr "Fehler: Ein Eltern-Element muss für diese Element Instanz vorliegen."
+
+# @ headway
+#: library/api/api-element.php:217
+msgid "Error: A CSS selector is required for this element instance."
+msgstr ""
+"Fehler: Eine CSS Auswahl (Selektor) muss für diese Element Instanz vorliegen."
+
+# @ headway
+#: library/api/api-element.php:252
+msgid "Error: The group being registered already exists."
+msgstr "Fehler: Die zu registrierende Gruppe existiert bereits."
+
+# @ headway
+#: library/api/api-panel.php:12
+msgid "Error: The panel class being registered does not exist."
+msgstr "Fehler: Die zu registrierende Panel Klasse existiert nicht."
+
+# @ headway
+#: library/blocks/blocks.php:87
+msgid "The block class being registered does not exist."
+msgstr "Die zu registrierende Block Klasse existiert nicht."
+
+# @ headway
+#: library/blocks/blocks.php:782
+msgid "The Headway blocks array does not exist."
+msgstr "Der Headway Blocks Array existiert nicht."
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:61
+msgid "Home"
+msgstr "Start"
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:104
+msgid "Search Results For:"
+msgstr "Suchergebnisse für:"
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:113
+msgid "Author Archives:"
+msgstr "Autoren-Archiv:"
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:120
+msgid "Tag Archives:"
+msgstr "Tag-Archiv:"
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:127
+msgid "Archives:"
+msgstr "Archiv:"
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:134
+msgid "Whoops! Page Not Found..."
+msgstr "Uuups! Die Seite wurde nicht gefunden..."
+
+# @ headway
+#: library/blocks/breadcrumbs/breadcrumbs.php:142
+msgid "You Are Here:"
+msgstr "Sie befinden sich hier:"
+
+# @ headway
+#: library/blocks/content/comments-template.php:54
+msgid "Sorry, comments are closed for this post."
+msgstr "Entschuldigung, Kommentare zu diesem Artikel sind nicht möglich."
+
+# @ headway
+#: library/blocks/content/comments-template.php:68
+msgid ""
+"This post is password protected. Please enter the password to view the "
+"comments."
+msgstr ""
+"Dieser Artikel ist passwortgeschützt. Bitte geben Sie das Passwort ein, um "
+"die Kommentare sehen zu können."
+
+# @ headway
+#: library/blocks/content/content-display.php:123
+#: library/blocks/listings/content-display.php:69
+msgid "
Sorry, there was no content that matched your search.
"
+msgstr ""
+"
Entschuldigung, es wurde kein Inhalt gefunden, der mit Ihrer Suchanfrage "
+"übereinstimmt.
Don't fret, you didn't do anything wrong. It appears that the page you "
+"are looking for does not exist or has been moved elsewhere.
"
+msgstr ""
+"
Nicht verzweifeln, Sie haben nichts falsch gemacht. Es scheint, als würde "
+"die Seite, die Sie suchen, nicht existieren oder als wäre Sie woanders hin "
+"verschoben worden.
There is no content to display. Please notify the site administrator or "
+"login.
"
+msgstr ""
+"
Kein Inhalt zum Anzeigen. Bitte informieren Sie den Seiten-Administrator "
+"oder melden Sie sich an.
"
+
+# @ headway
+#: library/fonts/traditional-fonts.php:127
+msgid ""
+"To register a font, the argument array must include an \"id\", \"stack\", "
+"and \"name\"."
+msgstr ""
+"Um eine Schrift zu registrieren, muss das Argument Array eine \"id\", \"stack"
+"\", und \"name\". enthalten."
+
+# @ default
+#: library/updater/theme-updater.php:66
+msgid ""
+"Before clicking OK to update, be sure that you have a backup of your website."
+msgstr ""
+"Bitte stellen Sie sicher, dass Sie ein Backup Ihrer Seite erstellt haben, "
+"bevor Sie auf OK zum aktualisieren klicken."
+
+# @ headway
+#: library/visual-editor/panels/design/property-inputs.php:151
+msgid "You have customized a property in this property group."
+msgstr "Sie haben eine Eigenschaft in dieser Eigenschafts-Gruppe angepasst."
+
+# @ headway
+#: library/visual-editor/panels/design/property-inputs.php:275
+msgid "You have customized this property."
+msgstr "Sie haben diese Eigenschaft angepasst."
diff --git a/wp-content/themes/headway/library/languages/headway.po b/wp-content/themes/headway/library/languages/headway.po
new file mode 100644
index 0000000..a77d6d7
--- /dev/null
+++ b/wp-content/themes/headway/library/languages/headway.po
@@ -0,0 +1,366 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Headway 3.6.x\n"
+"POT-Creation-Date: 2014-01-23 14:10-0600\n"
+"PO-Revision-Date: 2014-01-23 14:10-0600\n"
+"Last-Translator: Clay Griffiths \n"
+"Language-Team: Headway Themes \n"
+"Language: English\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.4\n"
+"X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_e\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: /Users/clay/Dropbox/Web/dev/wp-content/themes/"
+"headway\n"
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/admin/admin.php:146
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/admin/admin.php:183
+msgid "Please contact Headway Support if this error persists."
+msgstr ""
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/admin/admin.php:170
+msgid "License saved and activated."
+msgstr ""
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/admin/admin.php:174
+msgid ""
+"\n"
+"\t\t\t\t\tWhoops! Could not activate license. Please check "
+"that you have entered your license correctly and that it has not expired."
+"
There is no content to display. Please notify the site administrator or "
+"login.
"
+msgstr ""
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/fonts/traditional-fonts.php:127
+msgid ""
+"To register a font, the argument array must include an \"id\", \"stack\", "
+"and \"name\"."
+msgstr ""
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/updater/theme-updater.php:68
+msgid ""
+"Before clicking OK to update, be sure that you have a backup of your website."
+msgstr ""
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/visual-editor/panels/design/property-inputs.php:151
+msgid "You have customized a property in this property group."
+msgstr ""
+
+#: /Users/clay/Dropbox/Web/dev/wp-content/themes/headway/library/visual-editor/panels/design/property-inputs.php:274
+msgid "You have customized this property."
+msgstr ""
diff --git a/wp-content/themes/headway/library/languages/it_IT.mo b/wp-content/themes/headway/library/languages/it_IT.mo
new file mode 100644
index 0000000..f3ea981
Binary files /dev/null and b/wp-content/themes/headway/library/languages/it_IT.mo differ
diff --git a/wp-content/themes/headway/library/languages/it_IT.po b/wp-content/themes/headway/library/languages/it_IT.po
new file mode 100644
index 0000000..569f865
--- /dev/null
+++ b/wp-content/themes/headway/library/languages/it_IT.po
@@ -0,0 +1,451 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Headway Base v3.2.3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2012-07-15 13:48:36+0000\n"
+"Last-Translator: admin \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Poedit-Language: Italian\n"
+"X-Poedit-Country: ITALY\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
+"X-Poedit-Basepath: ../../\n"
+"X-Poedit-Bookmarks: \n"
+"X-Poedit-SearchPath-0: .\n"
+"X-Textdomain-Support: yes"
+
+#: library/admin/admin.php:358
+#, php-format
+#@ default
+msgid "
Remember!
Please backup before updating. Headway Themes recommends BackupBuddy for all backup and migration needs.
"
+msgstr ""
+
+#: library/api/api-admin-meta-box.php:12
+#@ headway
+msgid "The meta box class being registered does not exist."
+msgstr "La classe meta box che stai registrando non esiste."
+
+#: library/api/api-block.php:128
+#@ headway
+msgid "The block options class being registered does not exist."
+msgstr "La classe di opzioni per i blocchi che stai registrando non esiste."
+
+#: library/api/api-box.php:12
+#@ headway
+msgid "The box class being registered does not exist."
+msgstr "La classe di box che stai registrando non esiste."
+
+#: library/api/api-element.php:125
+#@ default
+msgid "Arguments must be an array for this element."
+msgstr ""
+
+#: library/api/api-element.php:150
+#@ default
+msgid "An ID is required for this element."
+msgstr ""
+
+#: library/api/api-element.php:153
+#@ default
+msgid "A name is required for this element."
+msgstr ""
+
+#: library/api/api-element.php:156
+#@ default
+msgid "A group is required for this element."
+msgstr ""
+
+#: library/api/api-element.php:159
+#@ default
+msgid "A CSS selector is required for this element."
+msgstr ""
+
+#: library/api/api-element.php:162
+#@ default
+msgid "Properties are required for this element."
+msgstr ""
+
+#: library/api/api-element.php:201
+#@ default
+msgid "Arguments must be an array for this element instance."
+msgstr ""
+
+#: library/api/api-element.php:217
+#@ default
+msgid "An ID is required for this element instance."
+msgstr ""
+
+#: library/api/api-element.php:220
+#@ default
+msgid "A name is required for this element instance."
+msgstr ""
+
+#: library/api/api-element.php:223
+#@ default
+msgid "A group is required for this element instance."
+msgstr ""
+
+#: library/api/api-element.php:226
+#@ default
+msgid "A parent element is required for this element instance."
+msgstr ""
+
+#: library/api/api-element.php:229
+#@ default
+msgid "A CSS selector is required for this element instance."
+msgstr ""
+
+#: library/api/api-element.php:239
+#@ default
+msgid "The element specified does not support instances."
+msgstr ""
+
+#: library/api/api-element.php:265
+#@ default
+msgid "The group being registered already exists."
+msgstr ""
+
+#: library/api/api-element.php:281
+#@ default
+msgid "Arguments must be an array for deregistering this element."
+msgstr ""
+
+#: library/api/api-element.php:293
+#@ default
+msgid "A group is required for deregistering this element."
+msgstr ""
+
+#: library/api/api-element.php:296
+#@ default
+msgid "An ID is required for deregistering this element."
+msgstr ""
+
+#: library/api/api-element.php:318
+#@ default
+msgid "Arguments must be an array for deregistering this element instance."
+msgstr ""
+
+#: library/api/api-element.php:331
+#@ default
+msgid "A group is required for deregistering this element instance."
+msgstr ""
+
+#: library/api/api-element.php:334
+#@ default
+msgid "An instance ID is required for deregistering this element instance."
+msgstr ""
+
+#: library/api/api-element.php:337
+#@ default
+msgid "An element is required for deregistering this element instance."
+msgstr ""
+
+#: library/api/api-element.php:357
+#@ default
+msgid "The group being deregistered does not exist."
+msgstr ""
+
+#: library/api/api-panel.php:12
+#@ headway
+msgid "The panel class being registered does not exist."
+msgstr "La classe di pannelli che stai registrando non esiste."
+
+#: library/api/api-panel.php:205
+#@ headway
+msgid "There are no inputs registered for this tab."
+msgstr "Non ci sono input registrati per questo tab."
+
+#: library/api/api-updater.php:168
+#, php-format
+#@ default
+msgid "
%s %s is now available, you're running %s! Your Headway license has expired. Please visit the Headway Dashboard to renew your license so you can continue to receive updates.
To save time, Headway allows you to "mirror" your blocks. If you already have a widget area or sidebar that's configured, you may choose to use it by using the select boxes below.
+
+
+
+
Header
+
+
+
+
+
+
+
+
Navigation
+
+
+
+
+
+
+
+
Content
+
+
+
+
+
+
+
+
+
+
Sidebar 1
+
+
+
+
+
+
+
+
Sidebar 2
+
+
+
+
+
+
+
+
+
+
+
+
+ Use Empty Grid
+
+ Next →';
+ echo 'Finish →';
+ echo '← Previous';
+ ?>
+
+
+
+
+
+
+
+
Choose a Layout to Clone
+
+
';
+ ?>
+
+
+ Use Empty Grid
+
+ Clone Layout →
+
+
+
+
+
+
+
Choose a Shared Layout
+
+
';
+ ?>
+
+
+ Use Empty Grid
+
+ Assign Layout →
+
+
+
+
+
+
+
+
+
Import Layout
+
Select the Headway Layout file you would like to import.
Note: When you browse to and select a file below the imported layout's blocks will automatically be added to the current layout.
+
+ Select File & Import
+
+
+
+
Export Current Layout
+
Clicking on the button below will package up the current layout and its blocks into a file to be saved and imported later.
+ Download Export File
+
+
+
+
+ $block ) {
+
+ //Get the block instance
+ $block = HeadwayBlocksData::get_block($block_id);
+
+ //If the block is mirrored, skip it
+ if ( headway_get('mirror-block', $block['settings'], false) )
+ continue;
+
+ //If the block is in the same layout as the current block, then do not allow it to be used as a block to mirror.
+ if ( $block['layout'] == headway_post('layout') )
+ continue;
+
+ //Create the default name by using the block type and ID
+ $default_name = HeadwayBlocks::block_type_nice($block['type']);
+
+ //If we can't get a name for the layout, then things probably aren't looking good. Just skip this block.
+ if ( !($layout_name = HeadwayLayout::get_name($block['layout'])) )
+ continue;
+
+ //Get alias if it exists, otherwise use the default name
+ $return .= '';
+
+ }
+
+ return $return;
+
+ }
+
+
+ static function clone_pages_select_walker($pages, $depth = 0) {
+
+ $return = '';
+
+ foreach($pages as $id => $children) {
+
+ $layout_id_fragments = explode(HeadwayLayout::$sep, $id);
+
+ $status = HeadwayLayout::get_status($id);
+
+ /* Take care of layouts that are the front page or blog index */
+ if ( get_option('show_on_front') === 'page' && (isset($layout_id_fragments[1]) && $layout_id_fragments[1] == 'page') ) {
+
+ /* If the page is set as the static homepage or blog page, hide it if they don't have children. */
+ if ( end($layout_id_fragments) == get_option('page_on_front') || end($layout_id_fragments) == get_option('page_for_posts') ) {
+
+ /* Layout has children--add the no edit class and has children class. */
+ if ( is_array($children) && count($children) !== 0 )
+ $disabled = true;
+
+ /* If the layout doesn't have children, then just hide it. */
+ else
+ continue;
+
+ }
+
+ }
+
+ /* Handle layouts that aren't customized or have a template */
+ if ( headway_get('customized', $status, false) === false || headway_get('template', $status, false) !== false ) {
+
+ /* If there ARE customized children, add the no-edit class */
+ if ( is_array($children) && count($children) !== 0 ) {
+
+ /* Check if the children are customized. */
+ if ( HeadwayVisualEditorDisplay::is_any_layout_child_customized($children) ) {
+
+ $disabled = true;
+
+ } else
+ continue;
+
+ /* If there aren't any children, do not display the node at all */
+ } else
+ continue;
+
+ }
+
+ /* If the current layout is selected, then make it disabled. */
+ if ( headway_post('layout') == $id )
+ $disabled = true;
+
+ /* Output Stuff */
+ $depth_display = str_repeat(' ', $depth);
+
+ $disabled = ( isset($disabled) && $disabled === true ) ? ' disabled="disabled"' : null;
+
+ $return .= '';
+
+ if ( is_array($children) && count($children) !== 0 )
+ $return .= self::clone_pages_select_walker($children, $depth + 1);
+
+ }
+
+ return $return;
+
+ }
+
+
+ static function templates_to_assign_select_options() {
+
+ $templates = HeadwayLayout::get_templates();
+
+ $return = '';
+
+ foreach ( $templates as $id => $name) {
+
+ $return .= '';
+
+ }
+
+ return $return;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/visual-editor/boxes/snapshots.php b/wp-content/themes/headway/library/visual-editor/boxes/snapshots.php
new file mode 100644
index 0000000..9970c70
--- /dev/null
+++ b/wp-content/themes/headway/library/visual-editor/boxes/snapshots.php
@@ -0,0 +1,63 @@
+Save Snapshot
+
+
+
' . "\n";
+
+ }
+
+
+ public static function list_pages($pages = null) {
+
+ //Since this function is recursive, we must designate the default like this
+ if ( $pages === null ) {
+
+ $pages = HeadwayLayout::get_pages();
+ $root_pages = true;
+
+ }
+
+ $return = '';
+
+ $return .= '
' . "\n";
+
+ /**
+ * Only show the message the function is being called for the first time (not showing children) and that the
+ * mode is NOT the grid and the grid is supported still.
+ **/
+ if ( isset($root_pages) && HeadwayVisualEditor::get_current_mode() !== 'grid' && current_theme_supports('headway-grid') ) {
+
+ $return .= '
To add blocks to a new layout, please switch to the Grid mode.
';
+
+ }
+
+ foreach ( $pages as $id => $children ) {
+
+ $layout_id_fragments = explode(HeadwayLayout::$sep, $id);
+
+ $status = HeadwayLayout::get_status($id, true);
+
+ $class = array('layout-item');
+
+ if ( is_array($children) && count($children) !== 0 )
+ $class[] = 'has-children';
+
+ if ( $status['customized'] === true && !$status['template'] && count(HeadwayBlocksData::get_blocks_by_layout($id)) > 0 )
+ $class[] = 'layout-item-customized';
+
+ if ( $status['template'] )
+ $class[] = 'layout-item-template-used';
+
+ if ( $id === headway_post('currentLayout') )
+ $class[] = 'layout-selected';
+
+ $template_id = ( $status['template'] ) ? 'template-' . $status['template'] : 'none';
+ $template_name = ( $status['template'] ) ? HeadwayLayout::get_name('template-' . $status['template']) : null;
+
+ /* Take care of layouts that are the front page or blog index */
+ if ( (get_option('show_on_front') === 'page' && (isset($layout_id_fragments[1]) && $layout_id_fragments[1] == 'page')) || apply_filters('headway_layout_selector_no_edit_item_' . $id, false) ) {
+
+ /* If the page is set as the static homepage or blog page, hide it if they don't have children. The Blog Index and Front Page layouts will override them. */
+ if ( end($layout_id_fragments) == get_option('page_on_front') || end($layout_id_fragments) == get_option('page_for_posts') || apply_filters('headway_layout_selector_no_edit_item_' . $id, false) ) {
+
+ /* Layout has children--add the no edit class and has children class. */
+ if ( is_array($children) && count($children) !== 0 ) {
+
+ $class[] = 'layout-item-no-edit';
+
+ /* If the layout doesn't have children, then just hide it. */
+ } else {
+
+ continue;
+
+ }
+
+ }
+
+ }
+
+ /* Add other classes */
+ if ( is_array($children) && count($children) && self::is_any_layout_child_customized($children) ) {
+ $class[] = 'has-children';
+ $class[] = 'has-customized-children';
+ }
+
+ /* Get post status */
+ $post_status = headway_get('post_status', $status);
+ $formatted_post_status = ($post_status && $post_status != 'Published') ? '(' . $post_status . ')' : null;
+
+ /* Output Stuff */
+ $return .= '
This element does not have any customized properties or instances.
';
+
+ echo '
';
+
+
+ echo '
';
+
+ echo '
';
+
+ echo '
';
+
+ }
+
+
+ public static function editor() {
+
+ echo '
+
+
+ Editing:
+
+
+
+ for all layouts
+
+
+
+ Customize For Current Layout
+ Customize Regular Element
+
+
+
+
+
+
+
+
+ ';
+
+ }
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/visual-editor/panels/grid/setup.php b/wp-content/themes/headway/library/visual-editor/panels/grid/setup.php
new file mode 100644
index 0000000..00c03a4
--- /dev/null
+++ b/wp-content/themes/headway/library/visual-editor/panels/grid/setup.php
@@ -0,0 +1,88 @@
+ 'Grid',
+ 'responsive-grid' => 'Responsive Grid'
+ );
+
+ public $tab_notices = array(
+ 'grid' => 'Note: the content in the grid above will not reflect how your site actually looks. The content inside the blocks is to give you a general reference while you wireframe and build the layout to your site.
The settings below are global and are not customized on a per-layout basis.',
+ 'responsive-grid' => 'The Headway Responsive Grid allows the powerful grid in Headway Base to be custom-tailored depending on the device that the visitor is viewing the site from. Please note: some sites may benefit from having the responsive grid enabled while other will not. As the designer of the website, it is up to you to decide. The responsive grid can be enabled or disabled at any time.'
+ );
+
+ public $inputs = array(
+ 'grid' => array(
+ 'columns' => array(
+ 'type' => 'slider',
+ 'name' => 'columns',
+ 'label' => 'Default Column Count', /* Column count is default only because you can't change it on the fly */
+ 'default' => 24,
+ 'tooltip' => 'The column count is the number of columns in the grid. This is represented by the grey regions on the grid.
This will NOT affect wrappers that are already created. It only affects wrappers that are created after this setting is changed.',
+ 'slider-min' => 6,
+ 'slider-max' => 24,
+ 'slider-interval' => 1,
+ 'callback' => 'Headway.defaultGridColumnCount = value.toString();updateGridWidthInput($(input).parents(".sub-tabs-content"));'
+ ),
+
+ 'column-width' => array(
+ 'type' => 'slider',
+ 'name' => 'column-width',
+ 'label' => 'Global Column Width',
+ 'default' => 20,
+ 'tooltip' => 'The column width is the amount of space inside of each column. This is represented by the grey regions on the grid.',
+ 'unit' => 'px',
+ 'slider-min' => 10,
+ 'slider-max' => 80,
+ 'slider-interval' => 1,
+ 'callback' => 'Headway.globalGridColumnWidth = value.toString();$i("div.wrapper:not(.independent-grid)").each(function() { $(this).headwayGrid("updateGridCSS"); });updateGridWidthInput($(input).parents(".sub-tabs-content"));'
+ ),
+
+ 'gutter-width' => array(
+ 'type' => 'slider',
+ 'name' => 'gutter-width',
+ 'label' => 'Global Gutter Width',
+ 'default' => 20,
+ 'tooltip' => 'The gutter width is the amount of space between each column. This is the space between each of the grey regions on the grid.',
+ 'unit' => 'px',
+ 'slider-min' => 0,
+ 'slider-max' => 40,
+ 'slider-interval' => 1,
+ 'callback' => 'Headway.globalGridGutterWidth = value.toString();$i("div.wrapper:not(.independent-grid)").each(function() { $(this).headwayGrid("updateGridCSS"); });updateGridWidthInput($(input).parents(".sub-tabs-content"));'
+ ),
+
+ 'grid-width' => array(
+ 'type' => 'integer',
+ 'unit' => 'px',
+ 'default' => 940,
+ 'name' => 'grid-width',
+ 'label' => 'Global Grid Width',
+ 'readonly' => true
+ )
+ ),
+
+ 'responsive-grid' => array(
+ 'enable-responsive-grid' => array(
+ 'type' => 'checkbox',
+ 'name' => 'enable-responsive-grid',
+ 'label' => 'Enable Responsive Grid',
+ 'default' => false,
+ 'tooltip' => 'If Headway\'s responsive grid is enabled, the grid will automatically adjust depending on the visitor\'s device (computer, iPhone, iPad, etc). Enabling the responsive grid can be extremely beneficial for some websites, but may not be worthwhile for other websites. If the responsive grid is enabled, the user will always have the option to disable the responsive grid via a link in the footer block.
Please Note: with the responsive grid enabled, the exact pixel widths of blocks may differ very slightly from when it is disabled.'
+ ),
+
+ 'responsive-video-resizing' => array(
+ 'type' => 'checkbox',
+ 'name' => 'responsive-video-resizing',
+ 'label' => 'Responsive Video Resizing',
+ 'default' => true,
+ 'tooltip' => 'If the Responsive Grid is enabled and the user visits the site when there are YouTube, Vimeo, or any other videos, then the videos will not resize properly unless then is checked.'
+ )
+ )
+ );
+
+}
+headway_register_visual_editor_panel('GridSetupPanel');
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/visual-editor/preview.php b/wp-content/themes/headway/library/visual-editor/preview.php
new file mode 100644
index 0000000..5724e40
--- /dev/null
+++ b/wp-content/themes/headway/library/visual-editor/preview.php
@@ -0,0 +1,24 @@
+ $option_value ) {
+
+ //This if statement is incredibly important and must not be tampered with and needs to be triple-checked if changed.
+ if ( preg_match('/^headway_(.*)?_preview$/', $option) && strpos($option, 'headway_') === 0 && strpos($option, '_preview') !== false ) {
+ delete_option($option);
+ }
+
+ }
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/visual-editor/scripts-min/app.js b/wp-content/themes/headway/library/visual-editor/scripts-min/app.js
new file mode 100644
index 0000000..b2f7dbb
--- /dev/null
+++ b/wp-content/themes/headway/library/visual-editor/scripts-min/app.js
@@ -0,0 +1 @@
+function ITStylesheet(e,t){return"undefined"!=typeof e.document&&(this.document=e.document,delete e.document),this.property_dom_names={},this.property_standard_names={},this.converted_rgb_values={},this.args="undefined"!=typeof e?e:{},this.action="undefined"!=typeof t?t:"load",this.init=function(){"find"===this.action?this._find_stylesheet():this._load_stylesheet()},this._load_stylesheet=function(){e=this.args;var t;"undefined"!=typeof e.href?(t=this.document.createElement("link"),t.href=e.href,this.type="link"):(t=this.document.createElement("style"),this.type="style"),t.type="text/css","undefined"!=typeof e.title&&(t.title=e.title),"undefined"!=typeof e.rel&&(t.rel=e.rel),"undefined"!=typeof e.media&&(t.media=e.media),"undefined"!=typeof e.href&&"undefined"==typeof e.rel&&(t.rel="stylesheet");var n="";"undefined"!=typeof e.content&&(n=e.content,delete e.content);var r=Math.floor(Math.random()*1e3)+1;this.$stylesheet_node=jQuery(t).insertBefore($i("style#live-css-holder")).addClass("ITStylesheet").attr("id","itstylesheet-"+r),this.stylesheet_node=this.$stylesheet_node[0];var i=this;jQuery.each(this.document.styleSheets,function(e,t){if(typeof t.ownerNode.id=="undefined"||!t.ownerNode.id||t.ownerNode.id!="itstylesheet-"+r)return;return i.stylesheet=t,!1}),this._find_rules(),""!==n&&this.set_rules(n)},this._find_stylesheet=function(){e=this.args;for(var t=0;t0){var r=t.shift();r=r.charAt(0).toUpperCase()+r.substr(1),n+=r}return this.property_dom_names[e]=n,n},this._get_property_standard_name=function(e){if("undefined"!=typeof this.property_standard_names[e])return this.property_standard_names[e];var t=e;return"padding-right-value"===e?t="padding-right":"padding-left-value"===e?t="padding-left":"margin-right-value"===e?t="margin-right":"margin-left-value"===e&&(t="margin-left"),this.property_standard_names[e]=t,t},this._delete_rule_at_index=function(e){this.stylesheet.deleteRule?this.stylesheet.deleteRule(e):this.stylesheet.removeRule(e)},this._get_stylesheet_rules=function(e){return e.cssRules?e.cssRules:e.rules},this._get_stylesheet_rules_object=function(e){var t=this._get_stylesheet_rules(e),n={},r=[];for(var i=0;i0)this._delete_rule_at_index(0)},this.delete_rule=function(e){var t=this.get_rule_index(e);return!1===t?!1:(this._delete_rule_at_index(t),!0)},this.delete_rule_property=function(e,t){var n={};n[t]=null,this.update_rule(e,n)},this._convert_rgb_to_hex=function(e){if("undefined"!=typeof this.converted_rgb_values[e])return this.converted_rgb_values[e];var t=/rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.exec(e),n=parseInt(t[1]),r=parseInt(t[2]),i=parseInt(t[3]),s=i|r<<8|n<<16;hex=s.toString(16).toUpperCase();while(hex.length<6)hex="0"+hex;return this.converted_rgb_values[e]="#"+hex,"#"+hex},this.get_stylesheet_text=function(){var e=this._get_stylesheet_rules_object(this.stylesheet),t="",n=/^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)/;for(selector in e){var r="";for(property in e[selector]){var i=e[selector][property];if("undefined"==typeof i)continue;n.test(i)&&(i=this._convert_rgb_to_hex(i)),r+=" "+property+": "+i+";\n"}if(""===r)continue;""!==t&&(t+="\n"),t+=selector+" {\n"+r+"}"}return t},this.get_computed_style=function(e){return window.getComputedStyle?window.getComputedStyle(e,""):e.currentStyle},this.set_rules=function(e){this.delete_all_rules(),"string"==typeof e&&(e=this._get_rules_obj_from_string(e));for(selector in e)this.update_rule(selector,e[selector])},this.init(),!0}define("util.misc",["jquery"],function(e){updateQueryStringParameter=function(e,t,n){var r=new RegExp("([?|&])"+t+"=.*?(&|$)","i"),i=e.indexOf("?")!==-1?"&":"?";return e.match(r)?e.replace(r,"$1"+t+"="+n+"$2"):e+i+t+"="+n},jQuery.fn.reverse=[].reverse,Number.prototype.toNearest=function(e){return Math.round(this/e)*e},Math._round=Math.round,Math.round=function(e,t){t=Math.abs(parseInt(t))||0;var n=Math.pow(10,t);return Math._round(e*n)/n},String.prototype.repeatStr=function(e){return e<=0?"":Array.prototype.join.call({length:e+1},this)},String.prototype.capitalize=function(){return this.replace(/(^|\s)([a-z])/g,function(e,t,n){return t+n.toUpperCase()})},hwBoolean=function(e){if(typeof e=="boolean")return e;if(typeof e=="undefined")return!1;if(typeof e=="number")return e===1?!0:e===0?!1:null;if(e===null)return!1;if(typeof e=="string"){var t=e.split(/\b/g);return t[0]==="1"||t[0]==="true"?!0:t[0]==="0"||t[0]==="false"?!1:null}return null},Number.prototype.toBool=function(){return this===1?!0:this===0?!1:null},String.prototype.toBool=function(){var e=this.split(/\b/g);return e[0]==="1"||e[0]==="true"?!0:e[0]==="0"||e[0]==="false"?!1:null},String.prototype.escapeHTML=function(){return this.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}}),define("util.loader",["jquery","util.misc"],function(e){createCog=function(t,n,r,i,s){if(e(t).length===0||e(t).find(".cog-container:visible").length)return!1;var r=typeof r=="undefined"?!1:r,o='
';return r?t.append(o):t.html(o),typeof s!="undefined"&&t.find(".cog-container").css({opacity:s}),!0},changeTitle=function(t){return e("title").text(t)},startTitleActivityIndicator=function(){return typeof titleActivityIndicatorInstance=="number"?!1:(titleActivityIndicatorInstance=window.setInterval(titleActivityIndicator,500),titleActivityIndicatorSavedTitle=e("title").text(),!0)},stopTitleActivityIndicator=function(){return typeof titleActivityIndicatorInstance!="number"?!1:(window.clearInterval(titleActivityIndicatorInstance),changeTitle(titleActivityIndicatorSavedTitle),delete titleActivityIndicatorCounter,delete titleActivityIndicatorSavedTitle,delete titleActivityIndicatorInstance,!0)},titleActivityIndicator=function(){typeof titleActivityIndicatorCounter=="undefined"&&(titleActivityIndicatorCounter=0,titleActivityIndicatorCounterPos=!0),titleActivityIndicatorCounterPos===!0?++titleActivityIndicatorCounter:--titleActivityIndicatorCounter,titleActivityIndicatorCounter===3?titleActivityIndicatorCounterPos=!1:titleActivityIndicatorCounter===0&&(titleActivityIndicatorCounterPos=!0);var e=titleActivityIndicatorSavedTitle+".".repeatStr(titleActivityIndicatorCounter);changeTitle(e)}}),function(){var DEBUG=!0;(function(undefined){var window=this||(0,eval)("this"),document=window.document,navigator=window.navigator,jQuery=window.jQuery,JSON=window.JSON;(function(e){if(typeof require=="function"&&typeof exports=="object"&&typeof module=="object"){var t=module.exports||exports;e(t)}else typeof define=="function"&&define.amd?define("ko",["exports"],e):e(window.ko={})})(function(e){function r(e,t){var r=e===null||typeof e in n;return r?e===t:!1}function i(e,t){var n;return function(){n||(n=setTimeout(function(){n=undefined,e()},t))}}function s(e,t){var n;return function(){clearTimeout(n),n=setTimeout(e,t)}}function o(e){var n=this;return e&&t.utils.objectForEach(e,function(e,r){var i=t.extenders[e];typeof i=="function"&&(n=i(n,r)||n)}),n}function d(e){t.bindingHandlers[e]={init:function(n,r,i,s,o){var u=function(){var t={};return t[e]=r(),t};return t.bindingHandlers.event.init.call(this,n,u,i,s,o)}}}function g(e,n,r,i){t.bindingHandlers[e]={init:function(e,s,o,u,a){var f,l;return t.computed(function(){var o=t.utils.unwrapObservable(s()),u=!r!=!o,c=!l,h=c||n||u!==f;h&&(c&&t.computedContext.getDependenciesCount()&&(l=t.utils.cloneNodes(t.virtualElements.childNodes(e),!0)),u?(c||t.virtualElements.setDomNodeChildren(e,t.utils.cloneNodes(l)),t.applyBindingsToDescendants(i?i(a,o):a,e)):t.virtualElements.emptyNode(e),f=u)},null,{disposeWhenNodeIsRemoved:e}),{controlsDescendantBindings:!0}}},t.expressionRewriting.bindingRewriteValidators[e]=!1,t.virtualElements.allowedBindings[e]=!0}var t=typeof e!="undefined"?e:{};t.exportSymbol=function(e,n){var r=e.split("."),i=t;for(var s=0;s",n[0]);return e>4?e:undefined}(),l=f===6,c=f===7;return{fieldsIncludedWithJsonPost:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],arrayForEach:function(e,t){for(var n=0,r=e.length;n0?e.splice(r,1):r===0&&e.shift()},arrayGetDistinctValues:function(e){e=e||[];var n=[];for(var r=0,i=e.length;r0){var i=r[0],s=i.parentNode;for(var o=0,u=n.length;o1){var n=e[0],r=e[e.length-1];e.length=0;while(n!==r){e.push(n),n=n.nextSibling;if(!n)return}e.push(r)}}return e},setOptionNodeSelectionState:function(e,t){f<7?e.setAttribute("selected",t):e.selected=t},stringTrim:function(e){return e===null||e===undefined?"":e.trim?e.trim():e.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},stringTokenize:function(e,n){var r=[],i=(e||"").split(n);for(var s=0,o=i.length;se.length?!1:e.substring(0,t.length)===t},domNodeIsContainedBy:function(e,t){if(e===t)return!0;if(e.nodeType===11)return!1;if(t.contains)return t.contains(e.nodeType===3?e.parentNode:e);if(t.compareDocumentPosition)return(t.compareDocumentPosition(e)&16)==16;while(e&&e!=t)e=e.parentNode;return!!e},domNodeIsAttachedToDocument:function(e){return t.utils.domNodeIsContainedBy(e,e.ownerDocument.documentElement)},anyDomNodeIsAttachedToDocument:function(e){return!!t.utils.arrayFirst(e,t.utils.domNodeIsAttachedToDocument)},tagNameLower:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},registerEventHandler:function(e,n,r){var i=f&&a[n];if(!i&&jQuery)jQuery(e).bind(n,r);else if(!i&&typeof e.addEventListener=="function")e.addEventListener(n,r,!1);else{if(typeof e.attachEvent=="undefined")throw new Error("Browser doesn't support addEventListener or attachEvent");var s=function(t){r.call(e,t)},o="on"+n;e.attachEvent(o,s),t.utils.domNodeDisposal.addDisposeCallback(e,function(){e.detachEvent(o,s)})}},triggerEvent:function(e,t){if(!e||!e.nodeType)throw new Error("element must be a DOM node when calling triggerEvent");var n=h(e,t);if(jQuery&&!n)jQuery(e).trigger(t);else if(typeof document.createEvent=="function"){if(typeof e.dispatchEvent!="function")throw new Error("The supplied element doesn't support dispatchEvent");var r=o[t]||"HTMLEvents",i=document.createEvent(r);i.initEvent(t,!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,e),e.dispatchEvent(i)}else if(n&&e.click)e.click();else{if(typeof e.fireEvent=="undefined")throw new Error("Browser doesn't support triggering events");e.fireEvent("on"+t)}},unwrapObservable:function(e){return t.isObservable(e)?e():e},peekObservable:function(e){return t.isObservable(e)?e.peek():e},toggleDomNodeCssClass:function(e,n,r){if(n){var i=/\S+/g,s=e.className.match(i)||[];t.utils.arrayForEach(n.match(i),function(e){t.utils.addOrRemoveItem(s,e,r)}),e.className=s.join(" ")}},setTextContent:function(e,n){var r=t.utils.unwrapObservable(n);if(r===null||r===undefined)r="";var i=t.virtualElements.firstChild(e);!i||i.nodeType!=3||t.virtualElements.nextSibling(i)?t.virtualElements.setDomNodeChildren(e,[e.ownerDocument.createTextNode(r)]):i.data=r,t.utils.forceRefresh(e)},setElementName:function(e,t){e.name=t;if(f<=7)try{e.mergeAttributes(document.createElement(""),!1)}catch(n){}},forceRefresh:function(e){if(f>=9){var t=e.nodeType==1?e:e.parentNode;t.style&&(t.style.zoom=t.style.zoom)}},ensureSelectElementIsRenderedCorrectly:function(e){if(f){var t=e.style.width;e.style.width=0,e.style.width=t}},range:function(e,n){e=t.utils.unwrapObservable(e),n=t.utils.unwrapObservable(n);var r=[];for(var i=e;i<=n;i++)r.push(i);return r},makeArray:function(e){var t=[];for(var n=0,r=e.length;n=0;o--)i(r[o])&&s.push(r[o]);return s},parseJson:function(e){if(typeof e=="string"){e=t.utils.stringTrim(e);if(e)return JSON&&JSON.parse?JSON.parse(e):(new Function("return "+e))()}return null},stringifyJson:function(e,n,r){if(!JSON||!JSON.stringify)throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");return JSON.stringify(t.utils.unwrapObservable(e),n,r)},postJson:function(n,r,i){i=i||{};var s=i.params||{},o=i.includeFields||this.fieldsIncludedWithJsonPost,u=n;if(typeof n=="object"&&t.utils.tagNameLower(n)==="form"){var a=n;u=a.action;for(var f=o.length-1;f>=0;f--){var l=t.utils.getFormFields(a,o[f]);for(var c=l.length-1;c>=0;c--)s[l[c].name]=l[c].value}}r=t.utils.unwrapObservable(r);var h=document.createElement("form");h.style.display="none",h.action=u,h.method="post";for(var p in r){var d=document.createElement("input");d.name=p,d.value=t.utils.stringifyJson(t.utils.unwrapObservable(r[p])),h.appendChild(d)}e(s,function(e,t){var n=document.createElement("input");n.name=e,n.value=t,h.appendChild(n)}),document.body.appendChild(h),i.submitter?i.submitter(h):h.submit(),setTimeout(function(){h.parentNode.removeChild(h)},0)}}}(),t.exportSymbol("utils",t.utils),t.exportSymbol("utils.arrayForEach",t.utils.arrayForEach),t.exportSymbol("utils.arrayFirst",t.utils.arrayFirst),t.exportSymbol("utils.arrayFilter",t.utils.arrayFilter),t.exportSymbol("utils.arrayGetDistinctValues",t.utils.arrayGetDistinctValues),t.exportSymbol("utils.arrayIndexOf",t.utils.arrayIndexOf),t.exportSymbol("utils.arrayMap",t.utils.arrayMap),t.exportSymbol("utils.arrayPushAll",t.utils.arrayPushAll),t.exportSymbol("utils.arrayRemoveItem",t.utils.arrayRemoveItem),t.exportSymbol("utils.extend",t.utils.extend),t.exportSymbol("utils.fieldsIncludedWithJsonPost",t.utils.fieldsIncludedWithJsonPost),t.exportSymbol("utils.getFormFields",t.utils.getFormFields),t.exportSymbol("utils.peekObservable",t.utils.peekObservable),t.exportSymbol("utils.postJson",t.utils.postJson),t.exportSymbol("utils.parseJson",t.utils.parseJson),t.exportSymbol("utils.registerEventHandler",t.utils.registerEventHandler),t.exportSymbol("utils.stringifyJson",t.utils.stringifyJson),t.exportSymbol("utils.range",t.utils.range),t.exportSymbol("utils.toggleDomNodeCssClass",t.utils.toggleDomNodeCssClass),t.exportSymbol("utils.triggerEvent",t.utils.triggerEvent),t.exportSymbol("utils.unwrapObservable",t.utils.unwrapObservable),t.exportSymbol("utils.objectForEach",t.utils.objectForEach),t.exportSymbol("utils.addOrRemoveItem",t.utils.addOrRemoveItem),t.exportSymbol("unwrap",t.utils.unwrapObservable),Function.prototype.bind||(Function.prototype.bind=function(e){var t=this,n=Array.prototype.slice.call(arguments),e=n.shift();return function(){return t.apply(e,n.concat(Array.prototype.slice.call(arguments)))}}),t.utils.domData=new function(){function r(r,i){var s=r[t],o=s&&s!=="null"&&n[s];if(!o){if(!i)return undefined;s=r[t]="ko"+e++,n[s]={}}return n[s]}var e=0,t="__ko__"+(new Date).getTime(),n={};return{get:function(e,t){var n=r(e,!1);return n===undefined?undefined:n[t]},set:function(e,t,n){if(n===undefined&&r(e,!1)===undefined)return;var i=r(e,!0);i[t]=n},clear:function(e){var r=e[t];return r?(delete n[r],e[t]=null,!0):!1},nextKey:function(){return e++ +t}}},t.exportSymbol("utils.domData",t.utils.domData),t.exportSymbol("utils.domData.clear",t.utils.domData.clear),t.utils.domNodeDisposal=new function(){function i(n,r){var i=t.utils.domData.get(n,e);return i===undefined&&r&&(i=[],t.utils.domData.set(n,e,i)),i}function s(n){t.utils.domData.set(n,e,undefined)}function o(e){var n=i(e,!1);if(n){n=n.slice(0);for(var s=0;s",""]||!n.indexOf("
",""]||(!n.indexOf("
","
"]||[0,"",""],s="ignored
"+i[1]+e+i[2]+"
";typeof window["innerShiv"]=="function"?r.appendChild(window.innerShiv(s)):r.innerHTML=s;while(i[0]--)r=r.lastChild;return t.utils.makeArray(r.lastChild.childNodes)}function r(e){if(jQuery.parseHTML)return jQuery.parseHTML(e)||[];var t=jQuery.clean([e]);if(t&&t[0]){var n=t[0];while(n.parentNode&&n.parentNode.nodeType!==11)n=n.parentNode;n.parentNode&&n.parentNode.removeChild(n)}return t}var e=/^(\s*)/;t.utils.parseHtmlFragment=function(e){return jQuery?r(e):n(e)},t.utils.setHtml=function(e,n){t.utils.emptyDomNode(e),n=t.utils.unwrapObservable(n);if(n!==null&&n!==undefined){typeof n!="string"&&(n=n.toString());if(jQuery)jQuery(e).html(n);else{var r=t.utils.parseHtmlFragment(n);for(var i=0;i"},unmemoize:function(t,n){var r=e[t];if(r===undefined)throw new Error("Couldn't find any memo with ID "+t+". Perhaps it's already been unmemoized.");try{return r.apply(null,n||[]),!0}finally{delete e[t]}},unmemoizeDomNodeAndDescendants:function(e,n){var r=[];i(e,r);for(var s=0,o=r.length;s0?(r.isDifferent(n,arguments[0])&&(r.valueWillMutate(),n=arguments[0],DEBUG&&(r._latestValue=n),r.valueHasMutated()),this):(t.dependencyDetection.registerDependency(r),n)}var n=e;return t.subscribable.call(r),t.utils.setPrototypeOfOrExtend(r,t.observable.fn),DEBUG&&(r._latestValue=n),r.peek=function(){return n},r.valueHasMutated=function(){r.notifySubscribers(n)},r.valueWillMutate=function(){r.notifySubscribers(n,"beforeChange")},t.exportProperty(r,"peek",r.peek),t.exportProperty(r,"valueHasMutated",r.valueHasMutated),t.exportProperty(r,"valueWillMutate",r.valueWillMutate),r},t.observable.fn={equalityComparer:r};var f=t.observable.protoProperty="__ko_proto__";t.observable.fn[f]=t.observable,t.utils.canSetPrototype&&t.utils.setPrototypeOf(t.observable.fn,t.subscribable.fn),t.hasPrototype=function(e,n){return e===null||e===undefined||e[f]===undefined?!1:e[f]===n?!0:t.hasPrototype(e[f],n)},t.isObservable=function(e){return t.hasPrototype(e,t.observable)},t.isWriteableObservable=function(e){return typeof e=="function"&&e[f]===t.observable?!0:typeof e=="function"&&e[f]===t.dependentObservable&&e.hasWriteFunction?!0:!1},t.exportSymbol("observable",t.observable),t.exportSymbol("isObservable",t.isObservable),t.exportSymbol("isWriteableObservable",t.isWriteableObservable),t.observableArray=function(e){e=e||[];if(typeof e=="object"&&"length"in e){var n=t.observable(e);return t.utils.setPrototypeOfOrExtend(n,t.observableArray.fn),n.extend({trackArrayChanges:!0})}throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.")},t.observableArray.fn={remove:function(e){var n=this.peek(),r=[],i=typeof e=="function"&&!t.isObservable(e)?e:function(t){return t===e};for(var s=0;s=0}):[]},destroy:function(e){var n=this.peek(),r=typeof e=="function"&&!t.isObservable(e)?e:function(t){return t===e};this.valueWillMutate();for(var i=n.length-1;i>=0;i--){var s=n[i];r(s)&&(n[i]._destroy=!0)}this.valueHasMutated()},destroyAll:function(e){return e===undefined?this.destroy(function(){return!0}):e?this.destroy(function(n){return t.utils.arrayIndexOf(e,n)>=0}):[]},indexOf:function(e){var n=this();return t.utils.arrayIndexOf(n,e)},replace:function(e,t){var n=this.indexOf(e);n>=0&&(this.valueWillMutate(),this.peek()[n]=t,this.valueHasMutated())}},t.utils.arrayForEach(["pop","push","reverse","shift","sort","splice","unshift"],function(e){t.observableArray.fn[e]=function(){var t=this.peek();this.valueWillMutate(),this.cacheDiffForKnownOperation(t,e,arguments);var n=t[e].apply(t,arguments);return this.valueHasMutated(),n}}),t.utils.arrayForEach(["slice"],function(e){t.observableArray.fn[e]=function(){var t=this();return t[e].apply(t,arguments)}}),t.utils.canSetPrototype&&t.utils.setPrototypeOf(t.observableArray.fn,t.observable.fn),t.exportSymbol("observableArray",t.observableArray);var l="arrayChange";t.extenders.trackArrayChanges=function(e){function o(){if(n)return;n=!0;var t=e.notifySubscribers;e.notifySubscribers=function(e,n){return(!n||n===u)&&++i,t.apply(this,arguments)};var s=[].concat(e.peek()||[]);r=null,e.subscribe(function(t){t=[].concat(t||[]);if(e.hasSubscriptionsForEvent(l)){var n=a(s,t);n.length&&e.notifySubscribers(n,l)}s=t,r=null,i=0})}function a(e,n){if(!r||i>1)r=t.utils.compareArrays(e,n,{sparse:!0});return r}if(e.cacheDiffForKnownOperation)return;var n=!1,r=null,i=0,s=e.subscribe;e.subscribe=e.subscribe=function(e,t,n){return n===l&&o(),s.apply(this,arguments)},e.cacheDiffForKnownOperation=function(e,s,o){function c(e,t,n){return u[u.length]={status:e,value:t,index:n}}if(!n||i)return;var u=[],a=e.length,f=o.length,l=0;switch(s){case"push":l=a;case"unshift":for(var h=0;h=0?(clearTimeout(T),T=setTimeout(p,e)):d._evalRateLimited?d._evalRateLimited():p()}function p(){if(o)return;if(a)return;if(w&&w()){if(!u){E();return}}else u=!1;o=!0;try{var e=S,r=x;t.dependencyDetection.begin({callback:function(t,n){a||(r&&e[n]?(S[n]=e[n],++x,delete e[n],--r):l(t,n))},computed:d,isInitial:!x}),S={},x=0;try{var c=n?f.call(n):f()}finally{t.dependencyDetection.end(),r&&t.utils.objectForEach(e,function(e,t){t.dispose()}),s=!1}d.isDifferent(i,c)&&(d.notifySubscribers(i,"beforeChange"),i=c,DEBUG&&(d._latestValue=i),(!d._evalRateLimited||d.throttleEvaluation)&&d.notifySubscribers(i))}finally{o=!1}x||E()}function d(){if(arguments.length>0){if(typeof g!="function")throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");return g.apply(n,arguments),this}return s&&p(),t.dependencyDetection.registerDependency(d),i}function v(){return s&&!x&&p(),i}function m(){return s||x>0}var i,s=!0,o=!1,u=!1,a=!1,f=e;f&&typeof f=="object"?(r=f,f=r.read):(r=r||{},f||(f=r.read));if(typeof f!="function")throw new Error("Pass a function that returns the value of the ko.computed");var g=r.write,y=r.disposeWhenNodeIsRemoved||r.disposeWhenNodeIsRemoved||null,b=r.disposeWhen||r.disposeWhen,w=b,E=c,S={},x=0,T=null;n||(n=r.owner),t.subscribable.call(d),t.utils.setPrototypeOfOrExtend(d,t.dependentObservable.fn),d.peek=v,d.getDependenciesCount=function(){return x},d.hasWriteFunction=typeof r.write=="function",d.dispose=function(){E()},d.isActive=m;var N=d.limit;return d.limit=function(e){N.call(d,e),d._evalRateLimited=function(){d._rateLimitedBeforeChange(i),s=!0,d._rateLimitedChange(d)}},t.exportProperty(d,"peek",d.peek),t.exportProperty(d,"dispose",d.dispose),t.exportProperty(d,"isActive",d.isActive),t.exportProperty(d,"getDependenciesCount",d.getDependenciesCount),y&&(u=!0,y.nodeType&&(w=function(){return!t.utils.domNodeIsAttachedToDocument(y)||b&&b()})),r.deferEvaluation!==!0&&p(),y&&m()&&y.nodeType&&(E=function(){t.utils.domNodeDisposal.removeDisposeCallback(y,E),c()},t.utils.domNodeDisposal.addDisposeCallback(y,E)),d},t.isComputed=function(e){return t.hasPrototype(e,t.dependentObservable)};var c=t.observable.protoProperty;t.dependentObservable[c]=t.observable,t.dependentObservable.fn={equalityComparer:r},t.dependentObservable.fn[c]=t.dependentObservable,t.utils.canSetPrototype&&t.utils.setPrototypeOf(t.dependentObservable.fn,t.subscribable.fn),t.exportSymbol("dependentObservable",t.dependentObservable),t.exportSymbol("computed",t.dependentObservable),t.exportSymbol("isComputed",t.isComputed),function(){function n(e,t,s){s=s||new i,e=t(e);var o=typeof e=="object"&&e!==null&&e!==undefined&&!(e instanceof Date)&&!(e instanceof String)&&!(e instanceof Number)&&!(e instanceof Boolean);if(!o)return e;var u=e instanceof Array?[]:{};return s.save(e,u),r(e,function(r){var i=t(e[r]);switch(typeof i){case"boolean":case"number":case"string":case"function":u[r]=i;break;case"object":case"undefined":var o=s.get(i);u[r]=o!==undefined?o:n(i,t,s)}}),u}function r(e,t){if(e instanceof Array){for(var n=0;n=0?this.values[r]=n:(this.keys.push(e),this.values.push(n))},get:function(e){var n=t.utils.arrayIndexOf(this.keys,e);return n>=0?this.values[n]:undefined}}}(),t.exportSymbol("toJS",t.toJS),t.exportSymbol("toJSON",t.toJSON),function(){var e="__ko__hasDomDataOptionValue__";t.selectExtensions={readValue:function(n){switch(t.utils.tagNameLower(n)){case"option":if(n[e]===!0)return t.utils.domData.get(n,t.bindingHandlers.options.optionValueDomDataKey);return t.utils.ieVersion<=7?n.getAttributeNode("value")&&n.getAttributeNode("value").specified?n.value:n.text:n.value;case"select":return n.selectedIndex>=0?t.selectExtensions.readValue(n.options[n.selectedIndex]):undefined;default:return n.value}},writeValue:function(n,r,i){switch(t.utils.tagNameLower(n)){case"option":switch(typeof r){case"string":t.utils.domData.set(n,t.bindingHandlers.options.optionValueDomDataKey,undefined),e in n&&delete n[e],n.value=r;break;default:t.utils.domData.set(n,t.bindingHandlers.options.optionValueDomDataKey,r),n[e]=!0,n.value=typeof r=="number"?r:""}break;case"select":if(r===""||r===null)r=undefined;var s=-1;for(var o=0,u=n.options.length,a;o=0||r===undefined&&n.size>1)n.selectedIndex=s;break;default:if(r===null||r===undefined)r="";n.value=r}}}}(),t.exportSymbol("selectExtensions",t.selectExtensions),t.exportSymbol("selectExtensions.readValue",t.selectExtensions.readValue),t.exportSymbol("selectExtensions.writeValue",t.selectExtensions.writeValue),t.expressionRewriting=function(){function r(r){if(t.utils.arrayIndexOf(e,r)>=0)return!1;var i=r.match(n);return i===null?!1:i[1]?"Object("+i[1]+")"+i[2]:r}function p(e){var n=t.utils.stringTrim(e);n.charCodeAt(0)===123&&(n=n.slice(1,-1));var r=[],i=n.match(l),s,o,u=0;if(i){i.push(",");for(var a=0,f;f=i[a];++a){var p=f.charCodeAt(0);if(p===44){if(u<=0){s&&r.push(o?{key:s,value:o.join("")}:{unknown:s}),s=o=u=0;continue}}else if(p===58){if(!o)continue}else if(p===47&&a&&f.length>1){var d=i[a-1].match(c);d&&!h[d[0]]&&(n=n.substr(n.indexOf(f)+1),i=n.match(l),i.push(","),a=-1,f="/")}else if(p===40||p===123||p===91)++u;else if(p===41||p===125||p===93)--u;else if(!s&&!o){s=p===34||p===39?f.slice(1,-1):f;continue}o?o.push(f):o=[f]}}return r}function v(e,n){function i(e,n){function f(t){return t&&t.preprocess?n=t.preprocess(n,e,i):!0}var a;if(!f(t.getBindingHandler(e)))return;d[e]&&(a=r(n))&&o.push("'"+e+"':function(_z){"+a+"=_z}"),u&&(n="function(){return "+n+" }"),s.push("'"+e+"':"+n)}n=n||{};var s=[],o=[],u=n.valueAccessors,a=typeof e=="string"?p(e):e;return t.utils.arrayForEach(a,function(e){i(e.key||e.unknown,e.value)}),o.length&&i("_ko_property_writers","{"+o.join(",")+" }"),s.join(",")}var e=["true","false","null","undefined"],n=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,i='"(?:[^"\\\\]|\\\\.)*"',s="'(?:[^'\\\\]|\\\\.)*'",o="/(?:[^/\\\\]|\\\\.)*/w*",u=",\"'{}()/:[\\]",a="[^\\s:,/][^"+u+"]*[^\\s"+u+"]",f="[^\\s]",l=RegExp(i+"|"+s+"|"+o+"|"+a+"|"+f,"g"),c=/[\])"'A-Za-z0-9_$]+$/,h={"in":1,"return":1,"typeof":1},d={};return{bindingRewriteValidators:[],twoWayBindings:d,parseObjectLiteral:p,preProcessBindings:v,keyValueArrayContainsKey:function(e,t){for(var n=0;n0?n[n.length-1].nextSibling:e.nextSibling:null}function f(e){var t=e.firstChild,n=null;if(t)do if(n)n.push(t);else if(s(t)){var r=a(t,!0);r?t=r:n=[t]}else o(t)&&(n=[t]);while(t=t.nextSibling);return n}var e=document&&document.createComment("test").text==="",n=e?/^$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,r=e?/^$/:/^\s*\/ko\s*$/,i={ul:!0,ol:!0};t.virtualElements={allowedBindings:{},childNodes:function(e){return s(e)?u(e):e.childNodes},emptyNode:function(e){if(!s(e))t.utils.emptyDomNode(e);else{var n=t.virtualElements.childNodes(e);for(var r=0,i=n.length;r=0:u?e.checked=r:e.checked=i()===r}var u=e.type=="checkbox",a=e.type=="radio";if(!u&&!a)return;var f=u&&t.utils.unwrapObservable(n())instanceof Array,l=f?i():undefined,c=a||f;a&&!e.name&&t.bindingHandlers.uniqueName.init(e,function(){return!0}),t.computed(s,null,{disposeWhenNodeIsRemoved:e}),t.utils.registerEventHandler(e,"click",s),t.computed(o,null,{disposeWhenNodeIsRemoved:e})}},t.expressionRewriting.twoWayBindings.checked=!0,t.bindingHandlers.checkedValue={update:function(e,n){e.value=t.utils.unwrapObservable(n())}}}();var p="__ko__cssValue";t.bindingHandlers.css={update:function(e,n){var r=t.utils.unwrapObservable(n());typeof r=="object"?t.utils.objectForEach(r,function(n,r){r=t.utils.unwrapObservable(r),t.utils.toggleDomNodeCssClass(e,n,r)}):(r=String(r||""),t.utils.toggleDomNodeCssClass(e,e[p],!1),e[p]=r,t.utils.toggleDomNodeCssClass(e,r,!0))}},t.bindingHandlers.enable={update:function(e,n){var r=t.utils.unwrapObservable(n());r&&e.disabled?e.removeAttribute("disabled"):!r&&!e.disabled&&(e.disabled=!0)}},t.bindingHandlers.disable={update:function(e,n){t.bindingHandlers.enable.update(e,function(){return!t.utils.unwrapObservable(n())})}},t.bindingHandlers.event={init:function(e,n,r,i,s){var o=n()||{};t.utils.objectForEach(o,function(o){typeof o=="string"&&t.utils.registerEventHandler(e,o,function(e){var u,a=n()[o];if(!a)return;try{var f=t.utils.makeArray(arguments);i=s.$data,f.unshift(i),u=a.apply(i,f)}finally{u!==!0&&(e.preventDefault?e.preventDefault():e.returnValue=!1)}var l=r.get(o+"Bubble")!==!1;l||(e.cancelBubble=!0,e.stopPropagation&&e.stopPropagation())})})}},t.bindingHandlers.foreach={makeTemplateValueAccessor:function(e){return function(){var n=e(),r=t.utils.peekObservable(n);return!r||typeof r.length=="number"?{foreach:n,templateEngine:t.nativeTemplateEngine.instance}:(t.utils.unwrapObservable(n),{foreach:r.data,as:r.as,includeDestroyed:r.includeDestroyed,afterAdd:r.afterAdd,beforeRemove:r.beforeRemove,afterRender:r.afterRender,beforeMove:r.beforeMove,afterMove:r.afterMove,templateEngine:t.nativeTemplateEngine.instance})}},init:function(e,n,r,i,s){return t.bindingHandlers.template.init(e,t.bindingHandlers.foreach.makeTemplateValueAccessor(n))},update:function(e,n,r,i,s){return t.bindingHandlers.template.update(e,t.bindingHandlers.foreach.makeTemplateValueAccessor(n),r,i,s)}},t.expressionRewriting.bindingRewriteValidators.foreach=!1,t.virtualElements.allowedBindings.foreach=!0;var v="__ko_hasfocusUpdating",m="__ko_hasfocusLastValue";t.bindingHandlers.hasfocus={init:function(e,n,r){var i=function(i){e[v]=!0;var s=e.ownerDocument;if("activeElement"in s){var o;try{o=s.activeElement}catch(u){o=s.body}i=o===e}var a=n();t.expressionRewriting.writeValueToProperty(a,r,"hasfocus",i,!0),e[m]=i,e[v]=!1},s=i.bind(null,!0),o=i.bind(null,!1);t.utils.registerEventHandler(e,"focus",s),t.utils.registerEventHandler(e,"focusin",s),t.utils.registerEventHandler(e,"blur",o),t.utils.registerEventHandler(e,"focusout",o)},update:function(e,n){var r=!!t.utils.unwrapObservable(n());!e[v]&&e[m]!==r&&(r?e.focus():e.blur(),t.dependencyDetection.ignore(t.utils.triggerEvent,null,[e,r?"focusin":"focusout"]))}},t.expressionRewriting.twoWayBindings.hasfocus=!0,t.bindingHandlers.hasFocus=t.bindingHandlers.hasfocus,t.expressionRewriting.twoWayBindings.hasFocus=!0,t.bindingHandlers.html={init:function(){return{controlsDescendantBindings:!0}},update:function(e,n){t.utils.setHtml(e,n())}},g("if"),g("ifnot",!1,!0),g("with",!0,!1,function(e,t){return e.createChildContext(t)});var y={};t.bindingHandlers.options={init:function(e){if(t.utils.tagNameLower(e)!=="select")throw new Error("options binding applies only to SELECT elements");while(e.length>0)e.remove(0);return{controlsDescendantBindings:!0}},update:function(e,n,r){function i(){return t.utils.arrayFilter(e.options,function(e){return e.selected})}function p(e,t,n){var r=typeof t;return r=="function"?t(e):r=="string"?e[t]:n}function v(n,i,s){s.length&&(h=s[0].selected?[t.selectExtensions.readValue(s[0])]:[],d=!0);var o=e.ownerDocument.createElement("option");if(n===y)t.utils.setTextContent(o,r.get("optionsCaption")),t.selectExtensions.writeValue(o,undefined);else{var u=p(n,r.get("optionsValue"),n);t.selectExtensions.writeValue(o,t.utils.unwrapObservable(u));var a=p(n,r.get("optionsText"),u);t.utils.setTextContent(o,a)}return[o]}function m(n,r){if(h.length){var i=t.utils.arrayIndexOf(h,t.selectExtensions.readValue(r[0]))>=0;t.utils.setOptionNodeSelectionState(r[0],i),d&&!i&&t.dependencyDetection.ignore(t.utils.triggerEvent,null,[e,"change"])}}var s=e.length==0,o=!s&&e.multiple?e.scrollTop:null,u=t.utils.unwrapObservable(n()),a=r.get("optionsIncludeDestroyed"),f={},l,c,h;e.multiple?h=t.utils.arrayMap(i(),t.selectExtensions.readValue):h=e.selectedIndex>=0?[t.selectExtensions.readValue(e.options[e.selectedIndex])]:[],u&&(typeof u.length=="undefined"&&(u=[u]),c=t.utils.arrayFilter(u,function(e){return a||e===undefined||e===null||!t.utils.unwrapObservable(e._destroy)}),r.has("optionsCaption")&&(l=t.utils.unwrapObservable(r.get("optionsCaption")),l!==null&&l!==undefined&&c.unshift(y)));var d=!1;f.beforeRemove=function(t){e.removeChild(t)};var g=m;r.has("optionsAfterRender")&&(g=function(e,n){m(e,n),t.dependencyDetection.ignore(r.get("optionsAfterRender"),null,[n[0],e!==y?e:undefined])}),t.utils.setDomNodeChildrenFromArrayMapping(e,c,v,f,g),t.dependencyDetection.ignore(function(){if(r.get("valueAllowUnset")&&r.has("value"))t.selectExtensions.writeValue(e,t.utils.unwrapObservable(r.get("value")),!0);else{var n;e.multiple?n=h.length&&i().length=0?t.selectExtensions.readValue(e.options[e.selectedIndex])!==h[0]:h.length||e.selectedIndex>=0,n&&t.utils.triggerEvent(e,"change")}}),t.utils.ensureSelectElementIsRenderedCorrectly(e),o&&Math.abs(o-e.scrollTop)>20&&(e.scrollTop=o)}},t.bindingHandlers.options.optionValueDomDataKey=t.utils.domData.nextKey(),t.bindingHandlers.selectedOptions={after:["options","foreach"],init:function(e,n,r){t.utils.registerEventHandler(e,"change",function(){var i=n(),s=[];t.utils.arrayForEach(e.getElementsByTagName("option"),function(e){e.selected&&s.push(t.selectExtensions.readValue(e))}),t.expressionRewriting.writeValueToProperty(i,r,"selectedOptions",s)})},update:function(e,n){if(t.utils.tagNameLower(e)!="select")throw new Error("values binding applies only to SELECT elements");var r=t.utils.unwrapObservable(n());r&&typeof r.length=="number"&&t.utils.arrayForEach(e.getElementsByTagName("option"),function(e){var n=t.utils.arrayIndexOf(r,t.selectExtensions.readValue(e))>=0;t.utils.setOptionNodeSelectionState(e,n)})}},t.expressionRewriting.twoWayBindings.selectedOptions=!0,t.bindingHandlers.style={update:function(e,n){var r=t.utils.unwrapObservable(n()||{});t.utils.objectForEach(r,function(n,r){r=t.utils.unwrapObservable(r),e.style[n]=r||""})}},t.bindingHandlers.submit={init:function(e,n,r,i,s){if(typeof n()!="function")throw new Error("The value for a submit binding must be a function");t.utils.registerEventHandler(e,"submit",function(t){var r,i=n();try{r=i.call(s.$data,e)}finally{r!==!0&&(t.preventDefault?t.preventDefault():t.returnValue=!1)}})}},t.bindingHandlers.text={init:function(){return{controlsDescendantBindings:!0}},update:function(e,n){t.utils.setTextContent(e,n())}},t.virtualElements.allowedBindings.text=!0,t.bindingHandlers.uniqueName={init:function(e,n){if(n()){var r="ko_unique_"+ ++t.bindingHandlers.uniqueName.currentIndex;t.utils.setElementName(e,r)}}},t.bindingHandlers.uniqueName.currentIndex=0,t.bindingHandlers.value={after:["options","foreach"],init:function(e,n,r){var i=["change"],s=r.get("valueUpdate"),o=!1;s&&(typeof s=="string"&&(s=[s]),t.utils.arrayPushAll(i,s),i=t.utils.arrayGetDistinctValues(i));var u=function(){o=!1;var i=n(),s=t.selectExtensions.readValue(e);t.expressionRewriting.writeValueToProperty(i,r,"value",s)},a=t.utils.ieVersion&&e.tagName.toLowerCase()=="input"&&e.type=="text"&&e.autocomplete!="off"&&(!e.form||e.form.autocomplete!="off");a&&t.utils.arrayIndexOf(i,"propertychange")==-1&&(t.utils.registerEventHandler(e,"propertychange",function(){o=!0}),t.utils.registerEventHandler(e,"focus",function(){o=!1}),t.utils.registerEventHandler(e,"blur",function(){o&&u()})),t.utils.arrayForEach(i,function(n){var r=u;t.utils.stringStartsWith(n,"after")&&(r=function(){setTimeout(u,0)},n=n.substring("after".length)),t.utils.registerEventHandler(e,n,r)})},update:function(e,n,r){var i=t.utils.unwrapObservable(n()),s=t.selectExtensions.readValue(e),o=i!==s;if(o)if(t.utils.tagNameLower(e)==="select"){var u=r.get("valueAllowUnset"),a=function(){t.selectExtensions.writeValue(e,i,u)};a(),!u&&i!==t.selectExtensions.readValue(e)?t.dependencyDetection.ignore(t.utils.triggerEvent,null,[e,"change"]):setTimeout(a,0)}else t.selectExtensions.writeValue(e,i)}},t.expressionRewriting.twoWayBindings.value=!0,t.bindingHandlers.visible={update:function(e,n){var r=t.utils.unwrapObservable(n()),i=e.style.display!="none";r&&!i?e.style.display="":!r&&i&&(e.style.display="none")}},d("click"),t.templateEngine=function(){},t.templateEngine.prototype.renderTemplateSource=function(e,t,n){throw new Error("Override renderTemplateSource")},t.templateEngine.prototype.createJavaScriptEvaluatorBlock=function(e){throw new Error("Override createJavaScriptEvaluatorBlock")},t.templateEngine.prototype.makeTemplateSource=function(e,n){if(typeof e=="string"){n=n||document;var r=n.getElementById(e);if(!r)throw new Error("Cannot find template with ID "+e);return new t.templateSources.domElement(r)}if(e.nodeType==1||e.nodeType==8)return new t.templateSources.anonymousTemplate(e);throw new Error("Unknown template type: "+e)},t.templateEngine.prototype.renderTemplate=function(e,t,n,r){var i=this.makeTemplateSource(e,r);return this.renderTemplateSource(i,t,n)},t.templateEngine.prototype.isTemplateRewritten=function(e,t){return this.allowTemplateRewriting===!1?!0:this.makeTemplateSource(e,t).data("isRewritten")},t.templateEngine.prototype.rewriteTemplate=function(e,t,n){var r=this.makeTemplateSource(e,n),i=t(r.text());r.text(i),r.data("isRewritten",!0)},t.exportSymbol("templateEngine",t.templateEngine),t.templateRewriting=function(){function r(e){var n=t.expressionRewriting.bindingRewriteValidators;for(var r=0;r/g;return{ensureTemplateIsRewritten:function(e,n,r){n.isTemplateRewritten(e,r)||n.rewriteTemplate(e,function(e){return t.templateRewriting.memoizeBindingAttributeSyntax(e,n)},r)},memoizeBindingAttributeSyntax:function(t,r){return t.replace(e,function(){return i(arguments[4],arguments[1],arguments[2],r)}).replace(n,function(){return i(arguments[1],"","#comment",r)})},applyMemoizedBindingsToNextSibling:function(e,n){return t.memoization.memoize(function(r,i){var s=r.nextSibling;s&&s.nodeName.toLowerCase()===n&&t.applyBindingAccessorsToNode(s,e,i)})}}}(),t.exportSymbol("__tr_ambtns",t.templateRewriting.applyMemoizedBindingsToNextSibling),function(){t.templateSources={},t.templateSources.domElement=function(e){this.domElement=e},t.templateSources.domElement.prototype.text=function(){var e=t.utils.tagNameLower(this.domElement),n=e==="script"?"text":e==="textarea"?"value":"innerHTML";if(arguments.length==0)return this.domElement[n];var r=arguments[0];n==="innerHTML"?t.utils.setHtml(this.domElement,r):this.domElement[n]=r};var e=t.utils.domData.nextKey()+"_";t.templateSources.domElement.prototype.data=function(n){if(arguments.length===1)return t.utils.domData.get(this.domElement,e+n);t.utils.domData.set(this.domElement,e+n,arguments[1])};var n=t.utils.domData.nextKey();t.templateSources.anonymousTemplate=function(e){this.domElement=e},t.templateSources.anonymousTemplate.prototype=new t.templateSources.domElement,t.templateSources.anonymousTemplate.prototype.constructor=t.templateSources.anonymousTemplate,t.templateSources.anonymousTemplate.prototype.text=function(){if(arguments.length==0){var e=t.utils.domData.get(this.domElement,n)||{};return e.textData===undefined&&e.containerData&&(e.textData=e.containerData.innerHTML),e.textData}var r=arguments[0];t.utils.domData.set(this.domElement,n,{textData:r})},t.templateSources.domElement.prototype.nodes=function(){if(arguments.length==0){var e=t.utils.domData.get(this.domElement,n)||{};return e.containerData}var r=arguments[0];t.utils.domData.set(this.domElement,n,{containerData:r})},t.exportSymbol("templateSources",t.templateSources),t.exportSymbol("templateSources.domElement",t.templateSources.domElement),t.exportSymbol("templateSources.anonymousTemplate",t.templateSources.anonymousTemplate)}(),function(){function n(e,n,r){var i,s=e,o=t.virtualElements.nextSibling(n);while(s&&(i=s)!==o)s=t.virtualElements.nextSibling(i),r(i,s)}function r(e,r){if(e.length){var i=e[0],s=e[e.length-1],o=i.parentNode,u=t.bindingProvider.instance,a=u.preprocessNode;if(a){n(i,s,function(e,t){var n=e.previousSibling,r=a.call(u,e);r&&(e===i&&(i=r[0]||t),e===s&&(s=r[r.length-1]||n))}),e.length=0;if(!i)return;i===s?e.push(i):(e.push(i,s),t.utils.fixUpContinuousNodeArray(e,o))}n(i,s,function(e){(e.nodeType===1||e.nodeType===8)&&t.applyBindings(r,e)}),n(i,s,function(e){(e.nodeType===1||e.nodeType===8)&&t.memoization.unmemoizeDomNodeAndDescendants(e,[r])}),t.utils.fixUpContinuousNodeArray(e,o)}}function i(e){return e.nodeType?e:e.length>0?e[0]:null}function s(n,s,o,u,a){a=a||{};var f=n&&i(n),l=f&&f.ownerDocument,c=a.templateEngine||e;t.templateRewriting.ensureTemplateIsRewritten(o,c,l);var h=c.renderTemplate(o,u,a,l);if(typeof h.length!="number"||h.length>0&&typeof h[0].nodeType!="number")throw new Error("Template engine must return an array of DOM nodes");var p=!1;switch(s){case"replaceChildren":t.virtualElements.setDomNodeChildren(n,h),p=!0;break;case"replaceNode":t.utils.replaceDomNodes(n,h),p=!0;break;case"ignoreTargetNode":break;default:throw new Error("Unknown renderMode: "+s)}return p&&(r(h,u),a.afterRender&&t.dependencyDetection.ignore(a.afterRender,null,[h,u.$data])),h}function u(e,n){var r=t.utils.domData.get(e,o);r&&typeof r.dispose=="function"&&r.dispose(),t.utils.domData.set(e,o,n&&n.isActive()?n:undefined)}var e;t.setTemplateEngine=function(n){if(!(n==undefined||n instanceof t.templateEngine))throw new Error("templateEngine must inherit from ko.templateEngine");e=n},t.renderTemplate=function(n,r,o,u,a){o=o||{};if((o["templateEngine"]||e)==undefined)throw new Error("Set a template engine before calling renderTemplate");a=a||"replaceChildren";if(u){var f=i(u),l=function(){return!f||!t.utils.domNodeIsAttachedToDocument(f)},c=f&&a=="replaceNode"?f.parentNode:f;return t.dependentObservable(function(){var e=r&&r instanceof t.bindingContext?r:new t.bindingContext(t.utils.unwrapObservable(r)),l=t.isObservable(n)?n():typeof n=="function"?n(e.$data,e):n,c=s(u,a,l,e,o);a=="replaceNode"&&(u=c,f=i(u))},null,{disposeWhen:l,disposeWhenNodeIsRemoved:c})}return t.memoization.memoize(function(e){t.renderTemplate(n,r,o,e,"replaceNode")})},t.renderTemplateForEach=function(e,n,i,o,u){var a,f=function(t,n){a=u.createChildContext(t,i.as,function(e){e.$index=n});var r=typeof e=="function"?e(t,a):e;return s(null,"ignoreTargetNode",r,a,i)},l=function(e,t,n){r(t,a),i.afterRender&&i.afterRender(t,e)};return t.dependentObservable(function(){var e=t.utils.unwrapObservable(n)||[];typeof e.length=="undefined"&&(e=[e]);var r=t.utils.arrayFilter(e,function(e){return i.includeDestroyed||e===undefined||e===null||!t.utils.unwrapObservable(e._destroy)});t.dependencyDetection.ignore(t.utils.setDomNodeChildrenFromArrayMapping,null,[o,r,f,i,l])},null,{disposeWhenNodeIsRemoved:o})};var o=t.utils.domData.nextKey();t.bindingHandlers.template={init:function(e,n){var r=t.utils.unwrapObservable(n());if(typeof r=="string"||r.name)t.virtualElements.emptyNode(e);else{var i=t.virtualElements.childNodes(e),s=t.utils.moveCleanedNodesToContainerElement(i);(new t.templateSources.anonymousTemplate(e)).nodes(s)}return{controlsDescendantBindings:!0}},update:function(e,n,r,i,s){var o=n(),a,f=t.utils.unwrapObservable(o),l=!0,c=null,h;typeof f=="string"?(h=o,f={}):(h=f.name,"if"in f&&(l=t.utils.unwrapObservable(f["if"])),l&&"ifnot"in f&&(l=!t.utils.unwrapObservable(f.ifnot)),a=t.utils.unwrapObservable(f.data));if("foreach"in f){var p=l&&f.foreach||[];c=t.renderTemplateForEach(h||e,p,f,e,s)}else if(!l)t.virtualElements.emptyNode(e);else{var d="data"in f?s.createChildContext(a,f.as):s;c=t.renderTemplate(h||e,d,f,e)}u(e,c)}},t.expressionRewriting.bindingRewriteValidators.template=function(e){var n=t.expressionRewriting.parseObjectLiteral(e);return n.length==1&&n[0].unknown?null:t.expressionRewriting.keyValueArrayContainsKey(n,"name")?null:"This template engine does not support anonymous templates nested within its templates"},t.virtualElements.allowedBindings.template=!0}(),t.exportSymbol("setTemplateEngine",t.setTemplateEngine),t.exportSymbol("renderTemplate",t.renderTemplate),t.utils.findMovesInArrayComparison=function(e,t,n){if(e.length&&t.length){var r,i,s,o,u;for(r=i=0;(!n||r0&&(t.utils.replaceDomNodes(o,u),i&&t.dependencyDetection.ignore(i,null,[r,u,s])),o.length=0,t.utils.arrayPushAll(o,u)},null,{disposeWhenNodeIsRemoved:e,disposeWhen:function(){return!t.utils.anyDomNodeIsAttachedToDocument(o)}});return{mappedNodes:o,dependentObservable:u.isActive()?u:undefined}}var n=t.utils.domData.nextKey();t.utils.setDomNodeChildrenFromArrayMapping=function(r,i,s,o,u){function E(e,n){w=f[n],d!==n&&(y[e]=w),w.indexObservable(d++),t.utils.fixUpContinuousNodeArray(w.mappedNodes,r),h.push(w),m.push(w)}function S(e,n){if(e)for(var r=0,i=n.length;r=0)return 2}catch(e){}return 1}();this.renderTemplateSource=function(e,r,i){i=i||{},t();var s=e.data("precompiled");if(!s){var o=e.text()||"";o="{{ko_with $item.koBindingContext}}"+o+"{{/ko_with}}",s=jQuery.template(null,o),e.data("precompiled",s)}var u=[r.$data],a=jQuery.extend({koBindingContext:r},i.templateOptions),f=n(s,u,a);return f.appendTo(document.createElement("div")),jQuery.fragments={},f},this.createJavaScriptEvaluatorBlock=function(e){return"{{ko_code ((function() { return "+e+" })()) }}"},this.addTemplate=function(e,t){document.write("';
+
+ }
+
+ }
+ /* End outputting dynamic JS and CSS */
+
+ }
+
+
+ public static function method_load_block_options() {
+
+ $layout = headway_post('layout');
+ $block_id = headway_post('block_id');
+ $unsaved_options = headway_post('unsaved_block_options', array());
+
+ $block = HeadwayBlocksData::get_block($block_id);
+
+ //If block is new, set the bare basics up
+ if ( !$block ) {
+
+ $block = array(
+ 'type' => headway_post('block_type'),
+ 'new' => true,
+ 'id' => $block_id,
+ 'layout' => $layout
+ );
+
+ }
+
+ /* Merge unsaved options in */
+ if ( is_array($unsaved_options) )
+ $block['settings'] = is_array(headway_get('settings', $block)) ? array_merge($block['settings'], $unsaved_options) : $unsaved_options;
+
+ do_action('headway_block_options_' . $block['type'], $block, $layout);
+
+ }
+
+
+ /* Wrapper Methods */
+ public static function method_load_wrapper_options() {
+
+ $layout_id = headway_post('layout');
+ $wrapper_id = headway_post('wrapper_id');
+ $unsaved_options = headway_post('unsaved_wrapper_options', array());
+
+ $wrapper = HeadwayWrappersData::get_wrapper($wrapper_id);
+
+ if ( !$wrapper ) {
+
+ $wrapper = array(
+ 'id' => $wrapper_id,
+ 'layout' => $layout_id,
+ 'new' => true
+ );
+
+ }
+
+ /* Merge unsaved options in */
+ if ( is_array($unsaved_options) )
+ $wrapper = array_merge($wrapper, $unsaved_options);
+
+ do_action('headway_wrapper_options', $wrapper, $layout_id);
+
+ }
+
+
+ /* Box methods */
+ public static function method_load_box_ajax_content() {
+
+ $layout = headway_post('layout');
+ $box_id = headway_post('box_id');
+
+ do_action('headway_visual_editor_ajax_box_content_' . $box_id);
+
+ }
+
+
+ /* Layout methods */
+ public static function method_get_layout_name() {
+
+ $layout = headway_post('layout');
+
+ echo HeadwayLayout::get_name($layout);
+
+ }
+
+
+ public static function secure_method_revert_layout() {
+
+ $layout = headway_post('layout_to_revert');
+
+ //Delete wrappers, blocks, design settings
+ HeadwayLayout::delete_layout($layout);
+
+ do_action('headway_visual_editor_reset_layout');
+
+ echo 'success';
+
+ }
+
+
+ /* Design editor methods */
+ public static function method_get_element_inputs() {
+
+ $element = headway_post('element');
+ $special_element_type = headway_post('specialElementType', false);
+ $special_element_meta = headway_post('specialElementMeta', false);
+ $group = $element['group'];
+
+ $unsaved_values = headway_post('unsavedValues', false);
+
+ /* Make sure that the library is loaded */
+ Headway::load('visual-editor/panels/design/property-inputs');
+
+ /* Get values */
+ if ( !$special_element_type && !$special_element_meta ) {
+
+ $property_values = HeadwayElementsData::get_element_properties($element['id']);
+ $property_values_excluding_defaults = HeadwayElementsData::get_element_properties($element['id'], true);
+
+ } else {
+
+ $property_values_args = array(
+ 'element' => $element['id'],
+ 'se_type' => $special_element_type,
+ 'se_meta' => $special_element_meta
+ );
+
+ $property_values = HeadwayElementsData::get_special_element_properties($property_values_args);
+ $property_values_excluding_defaults = HeadwayElementsData::get_special_element_properties(array_merge($property_values_args, array('exclude_default_data' => true)));
+
+ }
+
+ /* Merge in the unsaved values */
+ $property_values = is_array($unsaved_values) ? array_merge($property_values, $unsaved_values) : $property_values;
+ $property_values_excluding_defaults = is_array($unsaved_values) ? array_merge($property_values_excluding_defaults, $unsaved_values) : $property_values_excluding_defaults;
+
+ /* Display the appropriate inputs and values depending on the element */
+ HeadwayPropertyInputs::display($element, $special_element_type, $special_element_meta, $property_values, $property_values_excluding_defaults);
+
+ }
+
+
+ public static function method_get_design_editor_elements() {
+
+ $current_layout = headway_post('layout');
+ $all_elements = HeadwayElementAPI::get_all_elements();
+ $groups = HeadwayElementAPI::get_groups();
+
+ $customized_element_data = HeadwayElementsData::get_all_elements();
+
+ $elements = array('groups' => $groups);
+
+ /* Assemble the arrays */
+ foreach ( $all_elements as $element_id => $element_settings ) {
+
+ $elements[$element_id] = array(
+ 'selector' => $element_settings['selector'],
+ 'id' => $element_settings['id'],
+ 'parent' => headway_get('parent', $element_settings),
+ 'name' => $element_settings['name'],
+ 'description' => headway_get('description', $element_settings),
+ 'properties' => $element_settings['properties'],
+ 'group' => $element_settings['group'],
+ 'states' => headway_get('states', $element_settings, array()),
+ 'instances' => headway_get('instances', $element_settings, array()),
+ 'disallow-nudging' => headway_get('disallow-nudging', $element_settings, false),
+ 'inspectable' => headway_get('inspectable', $element_settings),
+ 'customized' => count( headway_get('properties', headway_get( $element_settings['id'], $customized_element_data), array()) ) ? true : false
+ );
+
+ /* Loop through main element instances and add customized flag if necessary */
+ foreach ( $elements[$element_id]['instances'] as $element_instance_id => $element_instance_settings ) {
+
+ if ( isset($customized_element_data[$element_settings['id']]['special-element-instance'][$element_instance_id]) )
+ $elements[$element_id]['instances'][$element_instance_id]['customized'] = true;
+
+ }
+
+ }
+
+ /* Spit it all out */
+ self::json_encode($elements);
+
+ }
+
+
+ public static function method_get_design_editor_element_data() {
+
+ self::json_encode(HeadwayElementsData::get_all_elements(true));
+
+ }
+
+
+ /* Template methods */
+ public static function secure_method_add_template() {
+
+ //Send the template ID back to JavaScript so it can be added to the list
+ self::json_encode(HeadwayLayout::add_template(headway_post('template_name')));
+
+ }
+
+
+ public static function secure_method_rename_layout_template() {
+
+ //Get templates
+ $templates = HeadwaySkinOption::get( 'list', 'templates', array() );
+
+ //Get template to rename
+ $id = str_replace('template-', '', headway_post( 'layout' ));
+
+ //Rename
+ if ( isset( $templates[ $id ] ) ) {
+
+ $templates[ $id ] = headway_post( 'newName' );
+
+ //Send back to database
+ HeadwaySkinOption::set( 'list', $templates, 'templates' );
+
+ do_action( 'headway_visual_editor_rename_template' );
+
+ echo 'success';
+
+ } else {
+
+ echo 'failure';
+
+ }
+
+ }
+
+
+ public static function secure_method_delete_template() {
+
+ //Retreive templates
+ $templates = HeadwaySkinOption::get('list', 'templates', array());
+
+ //Unset the deleted ID
+ $id = headway_post('template_to_delete');
+
+ //Delete template if it exists and send array back to DB
+ if ( isset($templates[$id]) ) {
+
+ unset($templates[$id]);
+
+ //Delete blocks, wrappers, DE settings for current skin
+ HeadwayLayout::delete_layout('template-' . $id);
+
+ //Delete template from templates list
+ HeadwaySkinOption::set('list', $templates, 'templates');
+
+ do_action('headway_visual_editor_delete_template');
+
+ echo 'success';
+
+ } else {
+
+ echo 'failure';
+
+ }
+
+ }
+
+
+ public static function secure_method_assign_template() {
+
+ $layout = headway_post('layout');
+ $template = str_replace('template-', '', headway_post('template'));
+
+ //Add the template flag
+ HeadwayLayoutOption::set($layout, 'template', $template);
+
+ //Add template flag to global template assignments for easier skin import/export
+ $template_assignments = HeadwaySkinOption::get('assignments', 'templates', array());
+ $template_assignments[$layout] = $template;
+
+ HeadwaySkinOption::set('assignments', $template_assignments, 'templates');
+
+ do_action('headway_visual_editor_assign_template');
+
+ echo HeadwayLayout::get_name('template-' . $template);
+
+ }
+
+
+ public static function secure_method_remove_template_from_layout() {
+
+ $layout = headway_post('layout');
+
+ //Remove the template flag
+ if ( !HeadwayLayoutOption::set($layout, 'template', false) ) {
+ echo 'failure';
+
+ return;
+ }
+
+ //Remove template flag from global template assignments for easier skin import/export
+ $template_assignments = HeadwaySkinOption::get('assignments', 'templates', array());
+ unset($template_assignments[$layout]);
+
+ HeadwaySkinOption::set('assignments', $template_assignments, 'templates');
+
+ do_action('headway_visual_editor_unassign_template');
+
+ echo 'success';
+
+ }
+
+
+ /* Micellaneous methods */
+ public static function method_clear_cache() {
+
+ if ( HeadwayCompiler::flush_cache(true) && HeadwayBlocks::clear_block_actions_cache() )
+ echo 'success';
+ else
+ echo 'failure';
+
+ }
+
+
+ public static function method_ran_tour() {
+
+ $mode = headway_post('mode');
+
+ HeadwayOption::set('ran-tour-' . $mode, true);
+
+ }
+
+
+ public static function method_fonts_list() {
+
+ return do_action('headway_fonts_ajax_list_fonts_' . headway_post('provider'));
+
+ }
+
+
+ public static function secure_method_redactor_upload_image() {
+
+ /* Insure that file is image */
+ if ( strpos($_FILES['file']['type'], 'image') !== 0 )
+ return false;
+
+ /* Use wp_handle_upload() */
+ /* Add this in to make wp_handle_upload pass validation */
+ $_POST['action'] = 'headway_visual_editor';
+
+ $upload = wp_handle_upload($_FILES['file'], array(
+ 'action' => 'headway_visual_editor'
+ ));
+
+ if ( isset($upload['error']) ) {
+ return false;
+ }
+
+ $attachment = array(
+ 'post_title' => $_FILES['file']['name'],
+ 'post_content' => '',
+ 'post_type' => 'attachment',
+ 'post_parent' => 0,
+ 'post_mime_type' => $upload['type'],
+ 'guid' => $upload['url']
+ );
+
+ // Create an Attachment in WordPress
+ $attachment_id = wp_insert_attachment( $attachment, $upload['file'], 0 );
+ wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload['file'] ));
+
+ /* Send URL back to VE */
+ self::json_encode(array(
+ 'filelink' => $upload['url']
+ ));
+
+ }
+
+
+ /* Data Portability */
+ /* General Data Portability */
+ public static function method_import_image() {
+
+ Headway::load('data/data-portability');
+
+ /* Set up variables */
+ $image_id = headway_post('imageID');
+ $image_contents = headway_post('imageContents');
+
+ /* Sideload image */
+ self::json_encode(HeadwayDataPortability::decode_image_to_uploads($image_contents['base64_contents']));
+
+ }
+
+ public static function method_import_images() {
+
+ Headway::load('data/data-portability');
+
+ /* Set up variables */
+ $import_file = headway_post('importFile');
+ $image_definitions = headway_get('image-definitions', $import_file, array());
+
+ $imported_images = array();
+
+ /* Loop through base64'd images and move them to uploads directory */
+ foreach ( $image_definitions as $image_id => $image )
+ $imported_images[$image_id] = HeadwayDataPortability::decode_image_to_uploads($image['base64_contents']);
+
+ /* Replace image variables in the import file */
+ foreach ( $imported_images as $imported_image_id => $imported_image ) {
+
+ /* Handle sideloading errors */
+ if ( headway_get('error', $imported_image) ) {
+
+ /* Replace entire array with error to stop import of settings */
+ $import_file = array(
+ 'error' => headway_get('error', $imported_image)
+ );
+
+ } else if ( headway_get('url', $imported_image) ) {
+
+ $import_file = self::import_images_recursive_replace($imported_image_id, $imported_image['url'], $import_file);
+
+ }
+
+ }
+
+ /* Remove giant image definitions from import file */
+ unset($import_file['image-definitions']);
+
+ /* Send import file with images replaced back to Visual Editor */
+ self::json_encode($import_file);
+
+ }
+
+
+ public static function replace_imported_images_variables($import_array) {
+
+ /* Check for imported images */
+ if ( empty($import_array['imported-images']) || !is_array($import_array['imported-images']) )
+ return $import_array;
+
+ /* Replace image variables in the import file */
+ foreach ( $import_array['imported-images'] as $imported_image_id => $imported_image ) {
+
+ if ( headway_get('url', $imported_image) ) {
+
+ $import_array = self::import_images_recursive_replace($imported_image_id, $imported_image['url'], $import_array);
+
+ /* Change erred image variable to point to a 404 image */
+ } else {
+
+ $import_array = self::import_images_recursive_replace($imported_image_id, 'IMAGE_NOT_UPLOADED', $import_array);
+
+ }
+
+ }
+
+ return $import_array;
+
+ }
+
+
+ public static function import_images_recursive_replace($variable, $replace, $array) {
+
+ if ( !is_array($array) )
+ return str_replace($variable, $replace, $array);
+
+ $processed_array = array();
+
+ foreach ( $array as $key => $value )
+ $processed_array[$key] = self::import_images_recursive_replace($variable, $replace, $value);
+
+ return $processed_array;
+
+ }
+
+
+ /* Skin Portability */
+ public static function method_export_skin() {
+
+ Headway::load('data/data-portability');
+
+ parse_str(headway_get('skin-info'), $skin_info);
+
+ return HeadwayDataPortability::export_skin($skin_info['skin-export-info']);
+
+ }
+
+
+ public static function method_install_skin() {
+
+ Headway::load('data/data-portability');
+
+ $skin_data = json_decode(stripslashes(headway_post('skin')), true);
+
+ if ( !is_array($skin_data) ) {
+ return self::json_encode(array(
+ 'error' => 'Could not install template.'
+ ));
+ }
+
+ $skin = self::replace_imported_images_variables($skin_data);
+
+ return self::json_encode(HeadwayDataPortability::install_skin($skin));
+
+ }
+
+
+ /* Layout Portability */
+ public static function method_export_layout() {
+
+ Headway::load('data/data-portability');
+
+ $layout = headway_get('layout', false);
+
+ return HeadwayDataPortability::export_layout($layout);
+
+ }
+
+
+ /* Block Settings Portability */
+ public static function method_export_block_settings() {
+
+ Headway::load('data/data-portability');
+
+ return HeadwayDataPortability::export_block_settings(headway_get('block-id'));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/wp-content/themes/headway/library/visual-editor/visual-editor.php b/wp-content/themes/headway/library/visual-editor/visual-editor.php
new file mode 100644
index 0000000..89e6479
--- /dev/null
+++ b/wp-content/themes/headway/library/visual-editor/visual-editor.php
@@ -0,0 +1,602 @@
+getSeverity() & $severity ) != 0 ) {
+ throw $error_ex;
+ }
+
+ }
+
+
+ public static function save($options, $current_layout = false, $mode = false) {
+
+ set_error_handler(array(__CLASS__, "ajax_error_handler"));
+
+ $output = array(
+ 'errors' => array()
+ );
+
+ if ( !$current_layout )
+ $current_layout = headway_post('layout');
+
+ if ( !$mode )
+ $mode = headway_post('mode');
+
+ //Handle triple slash bullshit
+ if ( get_magic_quotes_gpc() === 1 )
+ $options = array_map('stripslashes_deep', $options);
+
+ $blocks = isset($options['blocks']) ? $options['blocks'] : null;
+ $wrappers = isset($options['wrappers']) ? $options['wrappers'] : null;
+ $layout_options = isset($options['layout-options']) ? $options['layout-options'] : null;
+ $options_inputs = isset($options['options']) ? $options['options'] : null;
+ $design_editor_inputs = isset($options['design-editor']) ? $options['design-editor'] : null;
+
+ try {
+
+ /* Add wrappers */
+ if ( $wrappers ) {
+
+ foreach ( $wrappers as $id => $methods ) {
+
+ foreach ( $methods as $method => $value ) {
+
+ switch ( $method ) {
+
+ case 'new':
+
+ if ( HeadwayWrappersData::get_wrapper($id) )
+ continue;
+
+ if ( isset($wrappers[$id]['delete']) )
+ continue;
+
+ $args = array(
+ 'position' => headway_get('position', $wrappers[$id], 9999),
+ 'settings' => headway_get('settings', $wrappers[$id], array())
+ );
+
+ if ( $wrappers[$id]['insert_id'] ) {
+ $args['id'] = $wrappers[$id]['insert_id'];
+ }
+
+ $new_wrapper = HeadwayWrappersData::add_wrapper($current_layout, $args);
+
+ if ( is_wp_error($new_wrapper) ) {
+ $output['errors'][] = $new_wrapper->get_error_code() . ($new_wrapper->get_error_message() ? ' - ' . $new_wrapper->get_error_code() : '');
+ } else {
+ $output['wrapper-id-mapping'][$id] = $new_wrapper;
+ }
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+ /* End Adding wrappers */
+
+
+ /* Blocks */
+ if ( $blocks ) {
+
+ foreach ( $blocks as $id => $methods ) {
+
+ foreach ( $methods as $method => $value ) {
+
+ switch ( $method ) {
+
+ case 'new':
+
+ if ( HeadwayBlocksData::get_block($id) )
+ continue;
+
+ if ( isset($blocks[$id]['delete']) )
+ continue;
+
+ $dimensions = explode(',', $blocks[$id]['dimensions']);
+ $position = explode(',', $blocks[$id]['position']);
+
+ $settings = isset($blocks[$id]['settings']) ? $blocks[$id]['settings'] : array();
+
+ /* Check if the wrapper ID for the block is temporary, if it is get the real block ID */
+ if ( isset($output['wrapper-id-mapping']) && $added_wrapper_id = headway_get(HeadwayWrappers::format_wrapper_id($blocks[$id]['wrapper']), $output['wrapper-id-mapping']) ) {
+ $blocks[$id]['wrapper'] = $added_wrapper_id;
+ }
+
+ $args = array(
+ 'type' => $value,
+ 'wrapper' => $blocks[$id]['wrapper'],
+ 'position' => array(
+ 'left' => $position[0],
+ 'top' => $position[1]
+ ),
+ 'dimensions' => array(
+ 'width' => $dimensions[0],
+ 'height' => $dimensions[1]
+ ),
+ 'settings' => $settings
+ );
+
+ if ( $blocks[$id]['insert_id'] ) {
+ $args['id'] = $blocks[$id]['insert_id'];
+ }
+
+ $new_block = HeadwayBlocksData::add_block($current_layout, $args);
+
+ if ( is_wp_error($new_block) ) {
+ $output['errors'][] = $new_block->get_error_code() . ($new_block->get_error_message() ? ' - ' . $new_block->get_error_code() : '');
+ } else {
+ $output['block-id-mapping'][$id] = $new_block;
+ }
+
+ break;
+
+ case 'delete':
+
+ if ( isset($blocks[$id]['new']) )
+ continue;
+
+ HeadwayBlocksData::delete_block($id);
+
+ break;
+
+ case 'dimensions':
+
+ if ( isset($blocks[$id]['new']) )
+ continue;
+
+ $dimensions = explode(',', $value);
+
+ $args = array(
+ 'dimensions' => array(
+ 'width' => $dimensions[0],
+ 'height' => $dimensions[1]
+ )
+ );
+
+ HeadwayBlocksData::update_block($id, $args);
+
+ break;
+
+ case 'position':
+
+ if ( isset($blocks[$id]['new']) )
+ continue;
+
+ $position = explode(',', $value);
+
+ $args = array(
+ 'position' => array(
+ 'left' => $position[0],
+ 'top' => $position[1]
+ )
+ );
+
+ HeadwayBlocksData::update_block($id, $args);
+
+ break;
+
+ case 'wrapper':
+
+ if ( isset($blocks[$id]['new']) )
+ continue;
+
+ /* Check if the wrapper ID for the block is temporary, if it is get the real wrapper ID */
+ if ( isset($output['wrapper-id-mapping']) && headway_get($value, $output['wrapper-id-mapping']) )
+ $value = headway_get($value, $output['wrapper-id-mapping']);
+
+ $args = array(
+ 'wrapper' => $value
+ );
+
+
+ HeadwayBlocksData::update_block($id, $args);
+
+ break;
+
+ case 'settings':
+
+ if ( isset($blocks[$id]['new']) )
+ continue;
+
+ //Get the block from the layout
+ $block = HeadwayBlocksData::get_block($id);
+
+ //If block doesn't exist, we can't do anything.
+ if ( !$block || !is_array(headway_get('settings', $block)) )
+ continue;
+
+ //If there aren't any options, then don't do anything either
+ if ( !is_array($value) || count($value) === 0 )
+ continue;
+
+ $block['settings'] = array_merge($block['settings'], $value);
+
+ HeadwayBlocksData::update_block($id, $block);
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+ /* End Blocks */
+
+
+ /* Do everything else with wrappers. Reason being the wrapper IDs need to be established for adding blocks, but if we move a block from a wrapper then delete that wrapper, we don't want those blocks to be deleted. */
+ if ( $wrappers ) {
+
+ foreach ( $wrappers as $id => $methods ) {
+
+ foreach ( $methods as $method => $value ) {
+
+ switch ( $method ) {
+
+ case 'delete':
+
+ if ( isset($wrappers[$id]['new']) )
+ continue;
+
+ HeadwayWrappersData::delete_wrapper($current_layout, $id);
+
+ break;
+
+ case 'position':
+
+ if ( isset($wrappers[$id]['new']) )
+ continue;
+
+ $args = array(
+ 'position' => $value
+ );
+
+ HeadwayWrappersData::update_wrapper($id, $args);
+
+ break;
+
+ case 'settings':
+
+ if ( isset($wrappers[$id]['new']) )
+ continue;
+
+ //Get the wrapper from the layout so we can merge settings
+ $wrapper = HeadwayWrappersData::get_wrapper($id);
+
+ //If wrapper doesn't exist, we can't do anything.
+ if ( !$wrapper )
+ continue;
+
+ //If there aren't any options, then don't do anything either
+ if ( !is_array($value) || count($value) === 0 )
+ continue;
+
+ $wrapper['settings'] = array_merge($wrapper['settings'], $value);
+
+ HeadwayWrappersData::update_wrapper($id, $wrapper);
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+ /* End everything else wrappers (delete and options) */
+
+
+ /* Layout Options */
+ if ( $layout_options ) {
+
+ foreach ( $layout_options as $group => $options ) {
+
+ foreach ( $options as $option => $value ) {
+ HeadwayLayoutOption::set($current_layout, $option, $value, $group);
+ }
+
+ }
+
+ }
+ /* End Layout Options */
+
+ /* Options */
+ if ( $options_inputs ) {
+
+ foreach ( $options_inputs as $group => $options ) {
+
+ foreach ( $options as $option => $value ) {
+ HeadwaySkinOption::set($option, $value, $group);
+ }
+
+ }
+
+ }
+ /* End Options */
+
+ /* Design Editor Inputs */
+ if ( $design_editor_inputs ) {
+
+ /* Loop through to get every element and its properties */
+ foreach ( $design_editor_inputs as $element_id => $element_data ) {
+
+ if ( !is_array($element_data) )
+ continue;
+
+ //Dispatch depending on type of element data
+ foreach ( $element_data as $element_data_node => $element_data_node_data ) {
+
+ //Handle different nodes depending on what they are
+ if ( $element_data_node == 'properties' ) {
+
+ //Set each property for the regular element
+ foreach ( $element_data_node_data as $property_id => $property_value )
+ HeadwayElementsData::set_property(null, $element_id, $property_id, $property_value);
+
+ //Handle instances, states, etc.
+ } else if ( strpos($element_data_node, 'special-element-') === 0 ) {
+
+ $special_element_type = str_replace('special-element-', '', $element_data_node);
+
+ //Loop through the special elements
+ foreach ( $element_data_node_data as $special_element => $special_element_properties ) {
+
+ /* If block ID mapping exists, make sure that none of the temporary IDs are being a saved as instances. This is mainly to make block settimgs import work if they do it on a block that hasn't been saved yet. */
+ if ( isset($output['block-id-mapping']) && count($output['block-id-mapping']) ) {
+
+ foreach ( $output['block-id-mapping'] as $old_block_id => $new_block_id ) {
+ $special_element = str_replace('block-' . $old_block_id, 'block-' . $new_block_id, $special_element);
+ }
+
+ }
+
+ /* If wrapper ID mapping exists, do same thing as block ID mapping */
+ if ( isset( $output['wrapper-id-mapping'] ) && count( $output['wrapper-id-mapping'] ) ) {
+
+ foreach ( $output['wrapper-id-mapping'] as $old_wrapper_id => $new_wrapper_id ) {
+ $special_element = str_replace( 'wrapper-' . HeadwayWrappers::format_wrapper_id($old_wrapper_id), 'wrapper-' . HeadwayWrappers::format_wrapper_id( $new_wrapper_id ), $special_element );
+ }
+
+ }
+
+ //Set the special element properties now
+ foreach ( $special_element_properties as $special_element_property => $special_element_property_value ) {
+ HeadwayElementsData::set_special_element_property(null, $element_id, $special_element_type, $special_element, $special_element_property, $special_element_property_value);
+ }
+ }
+
+ }
+
+ }
+
+ }
+ /* End loop */
+
+ }
+ /* End Design Editor Inputs */
+
+ //This hook is used by cache flushing, plugins, etc. Do not fire on preview save because it'll flush preview options
+ if ( !headway_get('ve-preview') )
+ do_action('headway_visual_editor_save');
+
+ /* Save snapshot if allowed */
+ if ( !defined('HEADWAY_DISABLE_AUTO_SNAPSHOT') || HEADWAY_DISABLE_AUTO_SNAPSHOT !== true ) {
+ $output['snapshot'] = HeadwayDataSnapshots::save_snapshot(true);
+ }
+
+ } catch (Exception $e) {
+
+ /* Disable error output on saving right now */
+
+ /*
+ if ( !isset($output['errors']) || !is_array($output['errors']) )
+ $output['errors'] = array();
+
+ $output['errors'][] = $e->getMessage() . '
' . $e->getTraceAsString() . '
';
+ */
+
+ }
+
+ if ( !count($output['errors']) )
+ unset($output['errors']);
+
+ return $output;
+
+ }
+
+
+ public static function display() {
+
+ self::check_if_ie();
+
+ Headway::load('visual-editor/display', 'VisualEditorDisplay');
+ HeadwayVisualEditorDisplay::display();
+
+ }
+
+
+ public static function check_if_ie() {
+
+ /* Only show this on IE versions less than 9 */
+ if ( !headway_is_ie() || (headway_is_ie(9) || headway_is_ie(10) || headway_is_ie(11)) )
+ return false;
+
+ $message = '
+ Error
+
+ Unfortunately, the Headway Visual Editor does not work with Internet Explorer due to its lack of modern features.