Saved: 2018-03-19 19:52

Torey Heinz committed Mar 20, 2018
commit ad51d920120c4f34f4ca5db316089665330f4e15
Showing 18 changed files with 3149 additions and 170 deletions
app/content_types/marine_estimate_requests.yml +130 -0
@@ @@ -0,0 +1,130 @@
+ # Human readable name of this type
+ name: Marine estimate requests
+
+ # Lowercase, underscored handle used to access this type
+ slug: marine_estimate_requests
+
+ # Explanatory text displayed in the back-office
+ description: A description of the content type for the editors
+
+ # Slug of field used to identify entries by default, such as the title
+ label_field_name: name
+
+ # Valid values: manually, created_at, updated_at, or the slug of any field
+ order_by: manually
+
+ # Valid values: asc (ascending) and desc (descending). Set to asc by default.
+ # order_direction: asc
+
+ # Specify a field slug to group entries by that field in the back-office.
+ # group_by: <your field>
+
+ # Activate public 'create' API (e.g for a contact form)
+ # public_submission_enabled: false
+
+ # Array of emails to be notified of new entries made with the public API
+ # public_submission_accounts: ['john@example.com']
+
+ # Control the display of the content type in the back-office.
+ # display_settings:
+ # seo: false # display the SEO tab for the content entries
+ # advanced: false # display the Advanced tab for the content entries
+ # position: 1 # position in the sidebar menu
+ # hidden: false # hidden for authors?
+
+ # By default, the back-office displays the _label property (see label_field_name) of the content entry. This can be modified by writing your own Liquid template below:
+ # entry_template: '<a href="{{ link }}">{{ entry._label }}</a>' # The default template
+
+ # A list describing each field
+ fields:
+ - name: # The lowercase, underscored name of the field
+ label: Name # Human readable name of the field
+ type: string
+ required: true
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - email: # The lowercase, underscored name of the field
+ label: Email # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - phone: # The lowercase, underscored name of the field
+ label: Phone # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - vessel_description: # The lowercase, underscored name of the field
+ label: Vessel description # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - hull_number: # The lowercase, underscored name of the field
+ label: Hull number # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - location: # The lowercase, underscored name of the field
+ label: Location # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - marina: # The lowercase, underscored name of the field
+ label: Marina # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - completion_date: # The lowercase, underscored name of the field
+ label: Completion date # Human readable name of the field
+ type: string
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - message: # The lowercase, underscored name of the field
+ label: Message # Human readable name of the field
+ type: text
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+ # text_formatting: html # html (uses rich text editor), markdown or text (uses plain text editor)
+
+ - attachment_1: # The lowercase, underscored name of the field
+ label: Attachment 1 # Human readable name of the field
+ type: file
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - attachment_2: # The lowercase, underscored name of the field
+ label: Attachment 2 # Human readable name of the field
+ type: file
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - attachment_3: # The lowercase, underscored name of the field
+ label: Attachment 3 # Human readable name of the field
+ type: file
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
+
+ - attachment_4: # The lowercase, underscored name of the field
+ label: Attachment 4 # Human readable name of the field
+ type: file
+ required: false
+ hint: Explanatory text displayed in the back office
+ localized: false
app/views/pages/contact.liquid +4 -4
@@ @@ -1,13 +1,13 @@
---
- title: Contact Us
- handle: contact-us
+ title: Contact
+ handle: contact
slug: contact
listed: true
published: true
is_layout: false
editable_elements:
"main/heading": "Contact a Real Person, Who Really Cares."
- "main/content": "Wheither you are ready to get start or still have some questions, feel free to reach out, and we'll assist you anyway we can."
+ "main/content": "Whether you are ready to get start or still have some questions, feel free to reach out, and we'll assist you anyway we can."
---
{% extends 'layouts/page' %}
{% block 'main' %}
@@ @@ -43,7 +43,7 @@ editable_elements:
</div>
<div class="column medium-6">
- {% model_form 'customer_messages', success: '/contact-thank-you', error: '/contact', id: 'contact-form' %}
+ {% model_form 'customer_messages', success: '/thank-you', error: '/contact', id: 'contact-form' %}
{% if customer_message.errors %}
<p>The following errors occured:</p>
<ul>
app/views/pages/estimate.liquid +41 -155
@@ @@ -1,166 +1,52 @@
---
title: Estimate
handle: estimate
- slug: get-a-free-estimate
- listed: false
+ slug: estimate
+ listed: true
published: true
is_layout: false
editable_elements:
- "main/heading": "Get a Free Estimate"
- "main/content": "Our customers are the best, and we are honored to be able to serve them. "
+ "main/heading": "We can wait to get started on your project!"
+ "main/content": "When you're ready move forward with you project, this is the place to start. The more information you can give use here, the sooner we can get you an estimate. <p class='lead'>Complete the form below to get a free Estimate.</p>"
---
- {% extends 'layouts/page' %}
+ {% extends 'layouts/application' %}
{% block 'main' %}
{% include 'page_header' %}
- <section class="estimate">
- <form class="webform-client-form MultiFile-intercepted" enctype="multipart/form-data" action="/request-estimate?service_url=https%3A//www.canvasinnovations.us/marine-services/upholstery&amp;service_interest=Upholstery" method="post" id="webform-client-form-598" accept-charset="UTF-8">
- <div>
- <div class="form-item webform-component webform-component-markup" id="webform-component-personal-information-title">
- <div class="row">
- <h3>Personal Information</h3>
- <hr>
- <div class="column medium-4">
- <label>
- Name <small>(required)</small>
- <input type="text" name="submitted[first_name]" value="" size="30" maxlength="128" class="form-text required">
- </label>
- <label>
- Email <small> (required)</small>
- <input class="email form-text form-email required" type="email" id="edit-submitted-email-address" name="submitted[email_address]" size="30">
- </label>
- <label>
- Phone <small> (required)</small>
- <input type="text" id="edit-submitted-phone-number" name="submitted[phone_number]" value="" size="15" maxlength="128" class="form-text required">
- </label>
- </div>
- <div class="column medium-8">
- <label>
- Instructions, Comments, or Questions
- <div class="form-textarea-wrapper">
- <textarea style="height: 280px" id="edit-submitted-instructions-comments-or-questions" name="submitted[instructions_comments_or_questions]" class="form-textarea"></textarea>
- </div>
- </label>
- </div>
- </div>
- <hr>
- <div class="row">
- <div class="column medium-8">
- <h3>Vessel Information</h3>
- <hr>
- <label>
- Make/Model
- <input type="text" id="edit-submitted-make-model" name="submitted[make_model]" value="" size="30" maxlength="128" class="form-text">
- </label>
- <div class="form-item webform-component webform-component-number" id="webform-component-size">
- <label>
- Size <small> (required)</small>
- <input type="number" id="edit-submitted-size" name="submitted[size]" step="0.5" class="form-text form-number required"> <span class="field-suffix">Ft</span>
- </label>
- </div>
- <label>
- City <small> (required)</small>
- <input type="text" id="edit-submitted-vessel-city" name="submitted[vessel_city]" value="" size="30" maxlength="128" class="form-text required">
- </label>
- <div class="form-item webform-component webform-component-select" id="webform-component-vessel-state">
- <label>
- State <small> (required)</small>
- <select id="edit-submitted-vessel-state" name="submitted[vessel_state]" class="form-select required">
- <option value="" selected="selected">- Select -</option>
- <option value="IL">Illinois</option>
- <option value="IN">Indiana</option>
- <option value="MI">Michigan</option>
- <option value="OH">Ohio</option>
- </select>
- </label>
- </div>
- <label>
- Zip Code <small> (required)</small>
- <input type="text" id="edit-submitted-vessel-zip" name="submitted[vessel_zip]" value="" size="5" maxlength="128" class="form-text required">
- </label>
- <label>
- Marina
- <input type="text" id="edit-submitted-marina" name="submitted[marina]" value="" size="30" maxlength="128" class="form-text">
- </label>
- </div>
- <div class="column medium-4">
- <label>
- Services Requested <small> (required)</small>
- <div id="edit-submitted-services-requested" class="form-checkboxes">
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-enclosures">
- </label>
- <input type="checkbox" id="edit-submitted-services-requested-1" name="submitted[services_requested][enclosures]" value="enclosures" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-1">Enclosure </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-uphosltry">
- <input type="checkbox" id="edit-submitted-services-requested-2" name="submitted[services_requested][uphosltry]" value="uphosltry" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-2">Upholstry </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-tops">
- <input type="checkbox" id="edit-submitted-services-requested-3" name="submitted[services_requested][tops]" value="tops" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-3">Boat Tops </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-covers">
- <input type="checkbox" id="edit-submitted-services-requested-4" name="submitted[services_requested][covers]" value="covers" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-4">Covers </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-windows">
- <input type="checkbox" id="edit-submitted-services-requested-5" name="submitted[services_requested][windows]" value="windows" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-5">Bonded Windows </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-carpet">
- <input type="checkbox" id="edit-submitted-services-requested-6" name="submitted[services_requested][carpet]" value="carpet" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-6">Carpet </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-dodger">
- <input type="checkbox" id="edit-submitted-services-requested-7" name="submitted[services_requested][dodger]" value="dodger" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-7">Dodgers </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-headliners">
- <input type="checkbox" id="edit-submitted-services-requested-8" name="submitted[services_requested][headliners]" value="headliners" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-8">Headliners </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-repairs">
- <input type="checkbox" id="edit-submitted-services-requested-9" name="submitted[services_requested][repairs]" value="repairs" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-9">Repairs &amp; Stitching </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-framebending">
- <input type="checkbox" id="edit-submitted-services-requested-10" name="submitted[services_requested][framebending]" value="framebending" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-10">Custom Frame Bending </label>
- </div>
- <div class="form-item form-type-checkbox form-item-submitted-services-requested-misc">
- <input type="checkbox" id="edit-submitted-services-requested-11" name="submitted[services_requested][misc]" value="misc" class="form-checkbox">
- <label class="option" for="edit-submitted-services-requested-11">Misc/NA </label>
- </div>
- <label>
- Vessel Images
- <div class="MultiFile-wrap" id="edit-vessel-images-multi_wrap">
- <input class="form-item multi MultiFile-identifier-vessel-images-multi form-file jquery-once-1-processed MultiFile-applied" type="file" id="edit-vessel-images-multi" name="files[vessel_images_multi][]" size="60" value="">
- <div class="MultiFile-list" id="edit-vessel-images-multi_wrap_list"></div>
- </div>
- </label>
- <div class="description">Please upload any relevant images.</div>
- </div>
- </div>
- <div class="form-item webform-component webform-component-multifile" id="webform-component-vessel-images-multi">
- <div class="form-item form-type-file form-item-files-vessel-images-multi">
+ <section class="row page {{ page.slug }}">
+ <div class="column medium-6">
+ <div id="form-wrapper" class="callout">
+ <h2 class="text-center">{% editable_text "heading", line_break: false, format: 'raw', rows: 1 %}Heading{% endeditable_text %}</h2>
+ {% editable_text content %}Lorem ipsum{% endeditable_text %}
+ {% include 'estimate_form' %}
+ <hr>
+ <strong>Testimonial: </strong>
+ <div>
+ {% include 'random_testimonial' %}
+ </div>
+ </div>
+ </div>
+ <div class="column medium-6">
+ <div id="testimonials-wrapper" class="callout" style="height: 1200px; overflow: hidden;">
+ <p class="lead"><strong>Testimonials</strong></p>
+ {% include 'testimonials' %}
+ </div>
+ </div>
+ </section>
+ {% endblock %}
+ {% block body_bottom %}
+ <script type="text/javascript">
+ $(function() {
+ $('#testimonials-wrapper').height($('#form-wrapper').height() + 78);
+
+ $('#contact-form').on('submit', function(e) {
+ var form = $(this);
+ $('.robot-warning').addClass('hide')
- </div>
- <div class="outer">
- <div class="inner"></div>
- </div>
- <input type="hidden" name="submitted[vessel_images_multi][_fids]" value="">
- <input type="hidden" name="submitted[vessel_images_multi][_old_fids]">
- </div>
- <input type="hidden" name="details[sid]">
- <input type="hidden" name="details[page_num]" value="1">
- <input type="hidden" name="details[page_count]" value="1">
- <input type="hidden" name="details[finished]" value="0">
- <input type="hidden" name="form_build_id" value="form-XlJ0zOK1V4N95GlwBuj7VP0EwSksg8EYPRx8hgFY8Ko">
- <input type="hidden" name="form_id" value="webform_client_form_598">
- <div class="form-actions form-wrapper" id="edit-actions">
- <input class="btn btn-primary form-submit" type="submit" id="edit-submit" name="op" value="Submit">
- </div>
- </div>
- </form>
- </section>
+ if (grecaptcha.getResponse() == "") {
+ e.preventDefault();
+ $('.robot-warning').removeClass('hide')
+ }
+ });
+ });
+ </script>
{% endblock %}
app/views/pages/index.liquid +1 -1
@@ @@ -45,7 +45,7 @@ is_layout: false
<p class="lead"><a href="{% path_to service %}">{{ service.title }}</a></p>
</div>
<img src="{{ service.featured_image.url | resize: '400x300#' }}">
- <div class="card-section">
+ <div class="card-section hide-for-small-only">
{{ service.brief }}
</div>
</div>
app/views/pages/testimonials.liquid +1 -7
@@ @@ -22,13 +22,7 @@ editable_elements:
</p>
</div>
<hr class="thin">
- {% assign testimonials = contents.testimonials.all | shuffle %}
- {% for testimonial in testimonials %}
- <p class="callout offwhite">
- {{ testimonial.content }}<br>
- -- <strong>{{ testimonial.who }}</strong>
- </p>
- {% endfor %}
+ {% include 'testimonials' %}
</div>
</div>
</section>
app/views/pages/thank-you.liquid +26 -0
@@ @@ -0,0 +1,26 @@
+ ---
+ title: Thank You!
+ slug: thank-you
+ listed: false
+ published: true
+ is_layout: false
+ editable_elements:
+ "main/heading": "We'll be contacting you soon!"
+ "main/content": "We know you are excited to get started, while you wait, see what others have said."
+ ---
+ {% extends 'layouts/page' %}
+ {% block 'main' %}
+ {% include 'page_header' %}
+ <section class="row page {{ page.slug }}">
+ <div class="column medium-8 small-centered">
+ <div class="callout">
+ <h2 class="text-center">{% editable_text "heading", line_break: false, format: 'raw', rows: 1 %}Heading{% endeditable_text %}</h2>
+ <div class="text-center">
+ {% editable_text content %}Lorem ipsum{% endeditable_text %}
+ </div>
+ <hr class="thin">
+ {% include 'testimonials' %}
+ </div>
+ </div>
+ </section>
+ {% endblock %}
app/views/snippets/address_form.liquid +13 -0
@@ @@ -0,0 +1,13 @@
+ <label class="row">
+ Project Address:
+ <input name="content[address]" required="true" type="text" value="{{marine_estimate_request.address}}">
+ <input name="content[city]" required="true" type="text" value="{{marine_estimate_request.city}}">
+ <select name="content[state]" required="true">
+ <option value="" selected="selected">- Select -</option>
+ <option value="IL">Illinois</option>
+ <option value="IN">Indiana</option>
+ <option value="MI">Michigan</option>
+ <option value="OH">Ohio</option>
+ </select>
+ <input name="content[zip]" required="true" type="text" value="{{marine_estimate_request.zip}}">
+ </label>
app/views/snippets/estimate_form.liquid +47 -0
@@ @@ -0,0 +1,47 @@
+ {% model_form 'marine_estimate_requests', success: '/contact/thank-you', error: '/estimate', id: 'estimate-form' %}
+ {% if marine_estimate_request.errors %}
+ <p>The following errors occured:</p>
+ <ul>
+ {% for error in marine_estimate_request.errors %}
+ <li>{{error[0] | capitalize}} - {{error[1]}}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ <label>
+ Full Name:{% include 'required' %}
+ <input name="content[name]" required="true" type="text" value="{{marine_estimate_request.name}}">
+ </label>
+ <label>
+ Best Email:{% include 'required' %}
+ <input name="content[email]" required="true" type="email" value="{{marine_estimate_request.email}}">
+ </label>
+ <label>
+ Your Phone:{% include 'required' %}
+ <input name="content[phone]" required="true" type="tel" value="{{marine_estimate_request.phone}}">
+ </label>
+ <label>
+ Project Address:{% include 'required' %}
+ <p class="help-text thin">Please enter complete address</p>
+ <textarea name="content[address]" rows="2" required="true" placeholder="11276 E. Lakewood Blvd.
+ Holland, MI 49424 ">{{marine_estimate_request.address}}</textarea>
+ </label>
+ <label>
+ Project Location:
+ <p class="help-text thin">When applicable include: Marina, Dock/Slip number, location on property, etc.</p>
+ <textarea name="content[vessel_description]" rows="2">{{marine_estimate_request.vessel_description}}</textarea>
+ </label>
+ <label>
+ Work to be Completed:{% include 'required' %}
+ <textarea class="autosize" name="content[message]" rows="6" required="true" >{{marine_estimate_request.message}}</textarea>
+ </label>
+ <label>
+ When would you like your project completed by?
+ <input name="content[completion_date]" type="date" >
+ </label>
+ </tr>
+ <div class="robot-warning hide callout text-center warning">
+ Are you robot?
+ </div>
+ <div class="callout g-recaptcha text-center" data-sitekey="6LdbaUwUAAAAAFPucKMnLxCnYvIPBr3UQNOLYCE2"></div>
+ <input type="submit" class="button expanded large" value="Let's Get Started!">
+ {% endmodel_form %}
app/views/snippets/metatags.liquid +1 -1
@@ @@ -14,4 +14,4 @@
<meta property="og:image" content="{{ 'logo.png' | theme_image_url }}" />
<meta property="og:site_name" content="{{ site.name }}" />
<link rel="shortcut icon" href="{{ 'favicon.ico' | theme_image_url }}">
-
+ <meta name="trumbowyg-icons-path" content="{{ 'trumbowyg-icons.svg' | theme_image_url }}">
app/views/snippets/required.liquid +1 -0
@@ @@ -0,0 +1 @@
+ <sup style="color: #7A3C19"><em>(required)</em></sup>
app/views/snippets/testimonials.liquid +7 -0
@@ @@ -0,0 +1,7 @@
+ {% assign testimonial_list = contents.testimonials.all | shuffle %}
+ {% for testimonial in testimonial_list limit:10 %}
+ <p class="callout offwhite">
+ {{ testimonial.content }}<br>
+ -- <strong>{{ testimonial.who }}</strong>
+ </p>
+ {% endfor %}
data/marine_estimate_requests.yml +44 -0
@@ @@ -0,0 +1,44 @@
+ - "Sample 1":
+ email: "Vel voluptas est placeat deleniti in beatae."
+ phone: "Assumenda molestias eligendi id enim praesentium quia quaerat nihil."
+ vessel_description: "Est voluptas doloremque ea."
+ hull_number: "Eos veniam fugiat aspernatur consequatur dolor nemo."
+ location: "Quis alias et voluptatem."
+ marina: "Voluptate officia ipsam veniam eaque error iste nostrum."
+ completion_date: "Vel sunt eos et non."
+ message: "Cumque harum cupiditate natus consequatur ea itaque at. Optio hic illo quasi provident. Magnam voluptatum et tempora dolores fuga atque. Enim doloribus quasi eum et est."
+ # attachment_1: /samples/marine_estimate_requests/yourfile.txt # Path to a file in the public/samples folder or to a remote and external file.
+
+ - "Sample 2":
+ email: "Ipsum qui eum totam facere adipisci voluptatem."
+ phone: "A numquam quo rem velit facere adipisci voluptatem."
+ vessel_description: "Porro rerum laboriosam eveniet eligendi quisquam."
+ hull_number: "Non laborum ad dicta dolore iusto cupiditate."
+ location: "Consequatur tempora fugit autem ea blanditiis eum aut ex."
+ marina: "Voluptate sed maxime explicabo dolor."
+ completion_date: "Ea tempore repellat esse ut quam."
+ message: "Est voluptatem dolorem esse. Quo perspiciatis ut omnis molestiae porro ut libero. Neque omnis rerum repellendus animi minima."
+ # attachment_1: /samples/marine_estimate_requests/yourfile.txt # Path to a file in the public/samples folder or to a remote and external file.
+
+ - "Sample 3":
+ email: "Fugit ducimus alias velit eum esse."
+ phone: "Non quo laborum aut ducimus modi aperiam in consequatur."
+ vessel_description: "Nobis et natus quis."
+ hull_number: "Corrupti fugiat dicta quae nisi quos ea ab qui."
+ location: "Autem molestiae ut distinctio corporis optio voluptatem quisquam."
+ marina: "Reprehenderit enim velit minima."
+ completion_date: "Qui repellat quo et similique."
+ message: "Illum aut sed rerum sint. Qui exercitationem praesentium. Sit velit non voluptatem odit deserunt non. Tenetur ab possimus impedit."
+ # attachment_1: /samples/marine_estimate_requests/yourfile.txt # Path to a file in the public/samples folder or to a remote and external file.
+
+ - "Sample 4":
+ email: "Enim vero dicta cumque dolore voluptatem aut."
+ phone: "Fugit voluptas et omnis non quis ut."
+ vessel_description: "Numquam ut quibusdam earum veniam."
+ hull_number: "Omnis possimus fuga itaque non recusandae ducimus modi."
+ location: "Id provident alias ut reiciendis qui dolorem."
+ marina: "Et voluptatem sed magnam ullam dolorem aperiam."
+ completion_date: "Unde quia aperiam explicabo vel laboriosam occaecati."
+ message: "Aut porro fuga. Ea aperiam corrupti quia necessitatibus ut est optio. Et saepe quo illo at."
+ # attachment_1: /samples/marine_estimate_requests/yourfile.txt # Path to a file in the public/samples folder or to a remote and external file.
+
public/images/trumbowyg-icons.svg +1 -0
@@ @@ -0,0 +1 @@
+ <svg xmlns="http://www.w3.org/2000/svg"><symbol id="trumbowyg-blockquote" viewBox="0 0 72 72"><path d="M21.3 31.9h-.6c.8-1.2 1.9-2.2 3.4-3.2 2.1-1.4 5-2.7 9.2-3.3l-1.4-8.9c-4.7.7-8.5 2.1-11.7 4-2.4 1.4-4.3 3.1-5.8 4.9-2.3 2.7-3.7 5.7-4.5 8.5-.8 2.8-1 5.4-1 7.5 0 2.3.3 4 .4 4.8 0 .1.1.3.1.4 1.2 5.4 6.1 9.5 11.9 9.5 6.7 0 12.2-5.4 12.2-12.2s-5.5-12-12.2-12zM49.5 31.9h-.6c.8-1.2 1.9-2.2 3.4-3.2 2.1-1.4 5-2.7 9.2-3.3l-1.4-8.9c-4.7.7-8.5 2.1-11.7 4-2.4 1.4-4.3 3.1-5.8 4.9-2.3 2.7-3.7 5.7-4.5 8.5-.8 2.8-1 5.4-1 7.5 0 2.3.3 4 .4 4.8 0 .1.1.3.1.4 1.2 5.4 6.1 9.5 11.9 9.5 6.7 0 12.2-5.4 12.2-12.2s-5.5-12-12.2-12z"/></symbol><symbol id="trumbowyg-bold" viewBox="0 0 72 72"><path d="M51.1 37.8c-1.1-1.4-2.5-2.5-4.2-3.3 1.2-.8 2.1-1.8 2.8-3 1-1.6 1.5-3.5 1.5-5.3 0-2-.6-4-1.7-5.8-1.1-1.8-2.8-3.2-4.8-4.1-2-.9-4.6-1.3-7.8-1.3h-16v42h16.3c2.6 0 4.8-.2 6.7-.7 1.9-.5 3.4-1.2 4.7-2.1 1.3-1 2.4-2.4 3.2-4.1.9-1.7 1.3-3.6 1.3-5.7.2-2.5-.5-4.7-2-6.6zM40.8 50.2c-.6.1-1.8.2-3.4.2h-9V38.5h8.3c2.5 0 4.4.2 5.6.6 1.2.4 2 1 2.7 2 .6.9 1 2 1 3.3 0 1.1-.2 2.1-.7 2.9-.5.9-1 1.5-1.7 1.9-.8.4-1.7.8-2.8 1zm2.6-20.4c-.5.7-1.3 1.3-2.5 1.6-.8.3-2.5.4-4.8.4h-7.7V21.6h7.1c1.4 0 2.6 0 3.6.1s1.7.2 2.2.4c1 .3 1.7.8 2.2 1.7.5.9.8 1.8.8 3-.1 1.3-.4 2.2-.9 3z"/></symbol><symbol id="trumbowyg-close" viewBox="0 0 72 72"><path d="M57 20.5l-5.4-5.4-15.5 15.5-15.6-15.5-5.4 5.4L30.7 36 15.1 51.5l5.4 5.4 15.6-15.5 15.5 15.5 5.4-5.4L41.5 36z"/></symbol><symbol id="trumbowyg-create-link" viewBox="0 0 72 72"><path d="M31.1 48.9l-6.7 6.7c-.8.8-1.6.9-2.1.9s-1.4-.1-2.1-.9L15 50.4c-1.1-1.1-1.1-3.1 0-4.2l6.1-6.1.2-.2 6.5-6.5c-1.2-.6-2.5-.9-3.8-.9-2.3 0-4.6.9-6.3 2.6L11 41.8c-3.5 3.5-3.5 9.2 0 12.7l5.2 5.2c1.7 1.7 4 2.6 6.3 2.6s4.6-.9 6.3-2.6l6.7-6.7c2.5-2.6 3.1-6.7 1.5-10l-5.9 5.9zM38.7 22.5l6.7-6.7c.8-.8 1.6-.9 2.1-.9s1.4.1 2.1.9l5.2 5.2c1.1 1.1 1.1 3.1 0 4.2l-6.1 6.1-.2.2L42 38c1.2.6 2.5.9 3.8.9 2.3 0 4.6-.9 6.3-2.6l6.7-6.7c3.5-3.5 3.5-9.2 0-12.7l-5.2-5.2c-1.7-1.7-4-2.6-6.3-2.6s-4.6.9-6.3 2.6l-6.7 6.7c-2.7 2.7-3.3 6.9-1.7 10.2l6.1-6.1c0 .1 0 .1 0 0z"/><path d="M44.2 30.5c.2-.2.4-.6.4-.9 0-.3-.1-.6-.4-.9l-2.3-2.3c-.3-.2-.6-.4-.9-.4-.3 0-.6.1-.9.4L25.9 40.6c-.2.2-.4.6-.4.9 0 .3.1.6.4.9l2.3 2.3c.2.2.6.4.9.4.3 0 .6-.1.9-.4l14.2-14.2zM49.9 55.4h-8.5v-5h8.5v-8.9h5.2v8.9h8.5v5h-8.5v8.9h-5.2v-8.9z"/></symbol><symbol id="trumbowyg-del" viewBox="0 0 72 72"><path d="M45.8 45c0 1-.3 1.9-.9 2.8-.6.9-1.6 1.6-3 2.1s-3.1.8-5 .8c-2.1 0-4-.4-5.7-1.1-1.7-.7-2.9-1.7-3.6-2.7-.8-1.1-1.3-2.6-1.5-4.5l-.1-.8-6.7.6v.9c.1 2.8.9 5.4 2.3 7.6 1.5 2.3 3.5 4 6.1 5.1 2.6 1.1 5.7 1.6 9.4 1.6 2.9 0 5.6-.5 8-1.6 2.4-1.1 4.3-2.7 5.6-4.7 1.3-2 2-4.2 2-6.5 0-1.6-.3-3.1-.9-4.5l-.2-.6H44c0 .1 1.8 2.3 1.8 5.5zM29 28.9c-.8-.8-1.2-1.7-1.2-2.9 0-.7.1-1.3.4-1.9.3-.6.7-1.1 1.4-1.6.6-.5 1.4-.9 2.5-1.1 1.1-.3 2.4-.4 3.9-.4 2.9 0 5 .6 6.3 1.7 1.3 1.1 2.1 2.7 2.4 5.1l.1.9 6.8-.5v-.9c-.1-2.5-.8-4.7-2.1-6.7s-3.2-3.5-5.6-4.5c-2.4-1-5.1-1.5-8.1-1.5-2.8 0-5.3.5-7.6 1.4-2.3 1-4.2 2.4-5.4 4.3-1.2 1.9-1.9 3.9-1.9 6.1 0 1.7.4 3.4 1.2 4.9l.3.5h11.8c-2.3-.9-3.9-1.7-5.2-2.9zm13.3-6.2zM22.7 20.3zM13 34.1h46.1v3.4H13z"/></symbol><symbol id="trumbowyg-em" viewBox="0 0 72 72"><path d="M26 57l10.1-42h7.2L33.2 57H26z"/></symbol><symbol id="trumbowyg-fontsize" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 4v3h5v12h3V7h5V4H9zm-6 8h3v7h3v-7h3V9H3v3z"/></symbol><symbol id="trumbowyg-fullscreen" viewBox="0 0 72 72"><path d="M25.2 7.1H7.1v17.7l6.7-6.5 10.5 10.5 4.5-4.5-10.4-10.5zM47.2 7.1l6.5 6.7-10.5 10.5 4.5 4.5 10.5-10.4 6.7 6.8V7.1zM47.7 43.2l-4.5 4.5 10.4 10.5-6.8 6.7h18.1V47.2l-6.7 6.5zM24.3 43.2L13.8 53.6l-6.7-6.8v18.1h17.7l-6.5-6.7 10.5-10.5z"/><path fill="currentColor" d="M10.7 28.8h18.1V11.2l-6.6 6.4L11.6 7.1l-4.5 4.5 10.5 10.5zM60.8 28.8l-6.4-6.6 10.5-10.6-4.5-4.5-10.5 10.5-6.7-6.9v18.1zM60.4 64.9l4.5-4.5-10.5-10.5 6.9-6.7H43.2v17.6l6.6-6.4zM11.6 64.9l10.5-10.5 6.7 6.9V43.2H11.1l6.5 6.6L7.1 60.4z"/></symbol><symbol id="trumbowyg-h1" viewBox="0 0 72 72"><path d="M6.4 14.9h7.4v16.7h19.1V14.9h7.4V57h-7.4V38H13.8v19H6.4V14.9zM47.8 22.5c1.4 0 2.8-.1 4.1-.4 1.3-.2 2.5-.6 3.6-1.2 1.1-.5 2-1.3 2.8-2.1.8-.9 1.3-1.9 1.5-3.2h5.5v41.2h-7.4v-29H47.8v-5.3z"/></symbol><symbol id="trumbowyg-h2" viewBox="0 0 72 72"><path d="M1.5 14.9h7.4v16.7H28V14.9h7.4V57H28V38H8.8v19H1.5V14.9zM70.2 56.9H42c0-3.4.9-6.4 2.5-9s3.8-4.8 6.6-6.7c1.3-1 2.7-1.9 4.2-2.9 1.5-.9 2.8-1.9 4-3 1.2-1.1 2.2-2.2 3-3.4.8-1.2 1.2-2.7 1.2-4.3 0-.7-.1-1.5-.3-2.4s-.5-1.6-1-2.4c-.5-.7-1.2-1.3-2.1-1.8-.9-.5-2.1-.7-3.5-.7-1.3 0-2.4.3-3.3.8s-1.6 1.3-2.1 2.2-.9 2-1.2 3.3c-.3 1.3-.4 2.6-.4 4.1h-6.7c0-2.3.3-4.4.9-6.3.6-1.9 1.5-3.6 2.7-5 1.2-1.4 2.7-2.5 4.4-3.3 1.7-.8 3.8-1.2 6.1-1.2 2.5 0 4.6.4 6.3 1.2 1.7.8 3.1 1.9 4.1 3.1 1 1.3 1.8 2.6 2.2 4.1.4 1.5.6 2.9.6 4.2 0 1.6-.3 3.1-.8 4.5-.5 1.3-1.2 2.6-2.1 3.7-.9 1.1-1.8 2.2-2.9 3.1-1.1.9-2.2 1.8-3.4 2.7-1.2.8-2.4 1.6-3.5 2.4-1.2.7-2.3 1.5-3.3 2.2-1 .7-1.9 1.5-2.6 2.3-.7.8-1.3 1.7-1.5 2.6h20.1v5.9z"/></symbol><symbol id="trumbowyg-h3" viewBox="0 0 72 72"><path d="M1.4 14.5h7.4v16.7h19.1V14.5h7.4v42.1h-7.4v-19H8.8v19H1.4V14.5zM53.1 32.4c1.1 0 2.2 0 3.3-.2 1.1-.2 2.1-.5 2.9-1 .9-.5 1.6-1.2 2.1-2 .5-.9.8-1.9.8-3.2 0-1.8-.6-3.2-1.8-4.2-1.2-1.1-2.7-1.6-4.6-1.6-1.2 0-2.2.2-3.1.7-.9.5-1.6 1.1-2.2 1.9-.6.8-1 1.7-1.3 2.7-.3 1-.4 2-.4 3.1h-6.7c.1-2 .5-3.9 1.1-5.6.7-1.7 1.6-3.2 2.7-4.4s2.6-2.2 4.2-2.9c1.6-.7 3.5-1.1 5.6-1.1 1.6 0 3.2.2 4.7.7 1.6.5 2.9 1.2 4.2 2.1 1.2.9 2.2 2.1 3 3.4.7 1.4 1.1 3 1.1 4.8 0 2.1-.5 3.9-1.4 5.4-.9 1.6-2.4 2.7-4.4 3.4v.1c2.4.5 4.2 1.6 5.5 3.5 1.3 1.9 2 4.1 2 6.8 0 2-.4 3.7-1.2 5.3-.8 1.6-1.8 2.9-3.2 3.9-1.3 1.1-2.9 1.9-4.7 2.5-1.8.6-3.6.9-5.6.9-2.4 0-4.5-.3-6.3-1s-3.3-1.7-4.5-2.9c-1.2-1.3-2.1-2.8-2.7-4.5-.6-1.8-1-3.7-1-5.9h6.7c-.1 2.5.5 4.6 1.9 6.3 1.3 1.7 3.3 2.5 5.9 2.5 2.2 0 4.1-.6 5.6-1.9 1.5-1.3 2.3-3.1 2.3-5.4 0-1.6-.3-2.9-.9-3.8-.6-.9-1.5-1.7-2.5-2.2-1-.5-2.2-.8-3.4-.9-1.3-.1-2.6-.2-3.9-.1v-5.2z"/></symbol><symbol id="trumbowyg-h4" viewBox="0 0 72 72"><path d="M1.5 14.9h7.4v16.7H28V14.9h7.4V57H28V38H8.9v19H1.5V14.9zM70.5 47.2h-5.3V57h-6.4v-9.8H41.2v-6.7l17.7-24.8h6.4v26.2h5.3v5.3zm-24.2-5.3h12.5V23.7h-.1L46.3 41.9z"/></symbol><symbol id="trumbowyg-horizontal-rule" viewBox="0 0 72 72"><path d="M9.1 32h54v8h-54z"/></symbol><symbol id="trumbowyg-insert-image" viewBox="0 0 72 72"><path d="M64 17v38H8V17h56m8-8H0v54h72V9z"/><path d="M17.5 22C15 22 13 24 13 26.5s2 4.5 4.5 4.5 4.5-2 4.5-4.5-2-4.5-4.5-4.5zM16 50h27L29.5 32zM36 36.2l8.9-8.5L60.2 50H45.9S35.6 35.9 36 36.2z"/></symbol><symbol id="trumbowyg-italic" viewBox="0 0 72 72"><path d="M26 57l10.1-42h7.2L33.2 57H26z"/></symbol><symbol id="trumbowyg-justify-center" viewBox="0 0 72 72"><path d="M9 14h54v8H9zM9 50h54v8H9zM18 32h36v8H18z"/></symbol><symbol id="trumbowyg-justify-full" viewBox="0 0 72 72"><path d="M9 14h54v8H9zM9 50h54v8H9zM9 32h54v8H9z"/></symbol><symbol id="trumbowyg-justify-left" viewBox="0 0 72 72"><path d="M9 14h54v8H9zM9 50h54v8H9zM9 32h36v8H9z"/></symbol><symbol id="trumbowyg-justify-right" viewBox="0 0 72 72"><path d="M9 14h54v8H9zM9 50h54v8H9zM27 32h36v8H27z"/></symbol><symbol id="trumbowyg-lineheight" viewBox="0 0 72 72"><path d="M31 14h36v8H31zM31 50h36v8H31zM31 32h30v8H31z"/><path stroke-miterlimit="10" fill="none" stroke="currentColor" stroke-width="3.6428" d="M7.82 47.207l8.332 8.15 8.106-8.15M24.276 24.635l-8.333-8.15-8.105 8.15"/><path d="M14.347 53.761v-36h3.385v36z"/></symbol><symbol id="trumbowyg-link" viewBox="0 0 72 72"><path d="M30.9 49.1l-6.7 6.7c-.8.8-1.6.9-2.1.9s-1.4-.1-2.1-.9l-5.2-5.2c-1.1-1.1-1.1-3.1 0-4.2l6.1-6.1.2-.2 6.5-6.5c-1.2-.6-2.5-.9-3.8-.9-2.3 0-4.6.9-6.3 2.6L10.8 42c-3.5 3.5-3.5 9.2 0 12.7l5.2 5.2c1.7 1.7 4 2.6 6.3 2.6s4.6-.9 6.3-2.6l6.7-6.7C38 50.5 38.6 46.3 37 43l-6.1 6.1zM38.5 22.7l6.7-6.7c.8-.8 1.6-.9 2.1-.9s1.4.1 2.1.9l5.2 5.2c1.1 1.1 1.1 3.1 0 4.2l-6.1 6.1-.2.2-6.5 6.5c1.2.6 2.5.9 3.8.9 2.3 0 4.6-.9 6.3-2.6l6.7-6.7c3.5-3.5 3.5-9.2 0-12.7l-5.2-5.2c-1.7-1.7-4-2.6-6.3-2.6s-4.6.9-6.3 2.6l-6.7 6.7c-2.7 2.7-3.3 6.9-1.7 10.2l6.1-6.1z"/><path d="M44.1 30.7c.2-.2.4-.6.4-.9 0-.3-.1-.6-.4-.9l-2.3-2.3c-.2-.2-.6-.4-.9-.4-.3 0-.6.1-.9.4L25.8 40.8c-.2.2-.4.6-.4.9 0 .3.1.6.4.9l2.3 2.3c.2.2.6.4.9.4.3 0 .6-.1.9-.4l14.2-14.2z"/></symbol><symbol id="trumbowyg-ordered-list" viewBox="0 0 72 72"><path d="M27 14h36v8H27zM27 50h36v8H27zM27 32h36v8H27zM11.8 15.8V22h1.8v-7.8h-1.5l-2.1 1 .3 1.3zM12.1 38.5l.7-.6c1.1-1 2.1-2.1 2.1-3.4 0-1.4-1-2.4-2.7-2.4-1.1 0-2 .4-2.6.8l.5 1.3c.4-.3 1-.6 1.7-.6.9 0 1.3.5 1.3 1.1 0 .9-.9 1.8-2.6 3.3l-1 .9V40H15v-1.5h-2.9zM13.3 53.9c1-.4 1.4-1 1.4-1.8 0-1.1-.9-1.9-2.6-1.9-1 0-1.9.3-2.4.6l.4 1.3c.3-.2 1-.5 1.6-.5.8 0 1.2.3 1.2.8 0 .7-.8.9-1.4.9h-.7v1.3h.7c.8 0 1.6.3 1.6 1.1 0 .6-.5 1-1.4 1-.7 0-1.5-.3-1.8-.5l-.4 1.4c.5.3 1.3.6 2.3.6 2 0 3.2-1 3.2-2.4 0-1.1-.8-1.8-1.7-1.9z"/></symbol><symbol id="trumbowyg-p" viewBox="0 0 72 72"><path d="M47.8 15.1H30.1c-4.7 0-8.5 3.7-8.5 8.4s3.7 8.4 8.4 8.4v25h7V19.8h3v37.1h4.1V19.8h3.7v-4.7z"/></symbol><symbol id="trumbowyg-redo" viewBox="0 0 72 72"><path d="M10.8 51.2c0-5.1 2.1-9.7 5.4-13.1 3.3-3.3 8-5.4 13.1-5.4H46v-12L61.3 36 45.9 51.3V39.1H29.3c-3.3 0-6.4 1.3-8.5 3.5-2.2 2.2-3.5 5.2-3.5 8.5h-6.5z"/></symbol><symbol id="trumbowyg-removeformat" viewBox="0 0 72 72"><path d="M58.2 54.6L52 48.5l3.6-3.6 6.1 6.1 6.4-6.4 3.8 3.8-6.4 6.4 6.1 6.1-3.6 3.6-6.1-6.1-6.4 6.4-3.7-3.8 6.4-6.4zM21.7 52.1H50V57H21.7zM18.8 15.2h34.1v6.4H39.5v24.2h-7.4V21.5H18.8v-6.3z"/></symbol><symbol id="trumbowyg-strikethrough" viewBox="0 0 72 72"><path d="M45.8 45c0 1-.3 1.9-.9 2.8-.6.9-1.6 1.6-3 2.1s-3.1.8-5 .8c-2.1 0-4-.4-5.7-1.1-1.7-.7-2.9-1.7-3.6-2.7-.8-1.1-1.3-2.6-1.5-4.5l-.1-.8-6.7.6v.9c.1 2.8.9 5.4 2.3 7.6 1.5 2.3 3.5 4 6.1 5.1 2.6 1.1 5.7 1.6 9.4 1.6 2.9 0 5.6-.5 8-1.6 2.4-1.1 4.3-2.7 5.6-4.7 1.3-2 2-4.2 2-6.5 0-1.6-.3-3.1-.9-4.5l-.2-.6H44c0 .1 1.8 2.3 1.8 5.5zM29 28.9c-.8-.8-1.2-1.7-1.2-2.9 0-.7.1-1.3.4-1.9.3-.6.7-1.1 1.4-1.6.6-.5 1.4-.9 2.5-1.1 1.1-.3 2.4-.4 3.9-.4 2.9 0 5 .6 6.3 1.7 1.3 1.1 2.1 2.7 2.4 5.1l.1.9 6.8-.5v-.9c-.1-2.5-.8-4.7-2.1-6.7s-3.2-3.5-5.6-4.5c-2.4-1-5.1-1.5-8.1-1.5-2.8 0-5.3.5-7.6 1.4-2.3 1-4.2 2.4-5.4 4.3-1.2 1.9-1.9 3.9-1.9 6.1 0 1.7.4 3.4 1.2 4.9l.3.5h11.8c-2.3-.9-3.9-1.7-5.2-2.9zm13.3-6.2zM22.7 20.3zM13 34.1h46.1v3.4H13z"/></symbol><symbol id="trumbowyg-strong" viewBox="0 0 72 72"><path d="M51.1 37.8c-1.1-1.4-2.5-2.5-4.2-3.3 1.2-.8 2.1-1.8 2.8-3 1-1.6 1.5-3.5 1.5-5.3 0-2-.6-4-1.7-5.8-1.1-1.8-2.8-3.2-4.8-4.1-2-.9-4.6-1.3-7.8-1.3h-16v42h16.3c2.6 0 4.8-.2 6.7-.7 1.9-.5 3.4-1.2 4.7-2.1 1.3-1 2.4-2.4 3.2-4.1.9-1.7 1.3-3.6 1.3-5.7.2-2.5-.5-4.7-2-6.6zM40.8 50.2c-.6.1-1.8.2-3.4.2h-9V38.5h8.3c2.5 0 4.4.2 5.6.6 1.2.4 2 1 2.7 2 .6.9 1 2 1 3.3 0 1.1-.2 2.1-.7 2.9-.5.9-1 1.5-1.7 1.9-.8.4-1.7.8-2.8 1zm2.6-20.4c-.5.7-1.3 1.3-2.5 1.6-.8.3-2.5.4-4.8.4h-7.7V21.6h7.1c1.4 0 2.6 0 3.6.1s1.7.2 2.2.4c1 .3 1.7.8 2.2 1.7.5.9.8 1.8.8 3-.1 1.3-.4 2.2-.9 3z"/></symbol><symbol id="trumbowyg-subscript" viewBox="0 0 72 72"><path d="M32 15h7.8L56 57.1h-7.9L44.3 46H27.4l-4 11.1h-7.6L32 15zm-2.5 25.4h12.9L36 22.3h-.2l-6.3 18.1zM58.7 59.9c.6-1.4 2-2.8 4.1-4.4 1.9-1.3 3.1-2.3 3.7-2.9.8-.9 1.3-1.9 1.3-3 0-.9-.2-1.6-.7-2.2-.5-.6-1.2-.9-2.1-.9-1.2 0-2.1.5-2.5 1.4-.3.5-.4 1.4-.5 2.5h-4c.1-1.8.4-3.2 1-4.3 1.1-2.1 3-3.1 5.8-3.1 2.2 0 3.9.6 5.2 1.8 1.3 1.2 1.9 2.8 1.9 4.8 0 1.5-.5 2.9-1.4 4.1-.6.8-1.6 1.7-3 2.6L66 57.7c-1 .7-1.7 1.2-2.1 1.6-.4.3-.7.7-1 1.1H72V64H57.8c0-1.5.3-2.8.9-4.1z"/></symbol><symbol id="trumbowyg-superscript" viewBox="0 0 72 72"><path d="M32 15h7.8L56 57.1h-7.9l-4-11.1H27.4l-4 11.1h-7.6L32 15zm-2.5 25.4h12.9L36 22.3h-.2l-6.3 18.1zM49.6 28.8c.5-1.1 1.6-2.3 3.4-3.6 1.5-1.1 2.5-1.9 3-2.4.7-.7 1-1.6 1-2.4 0-.7-.2-1.3-.6-1.8-.4-.5-1-.7-1.7-.7-1 0-1.7.4-2.1 1.1-.2.4-.3 1.1-.4 2.1H49c.1-1.5.3-2.6.8-3.5.9-1.7 2.5-2.6 4.8-2.6 1.8 0 3.2.5 4.3 1.5 1.1 1 1.6 2.3 1.6 4 0 1.3-.4 2.4-1.1 3.4-.5.7-1.3 1.4-2.4 2.2l-1.3 1c-.8.6-1.4 1-1.7 1.3-.3.3-.6.6-.8.9h7.4v3H48.8c0-1.3.3-2.4.8-3.5z"/></symbol><symbol id="trumbowyg-table" viewBox="0 0 72 72"><path d="M25.686 51.38v-6.347q0-.462-.297-.76-.298-.297-.761-.297H14.04q-.463 0-.761.297-.298.298-.298.76v6.346q0 .463.298.76.298.298.76.298h10.589q.463 0 .76-.298.298-.297.298-.76zm0-12.692v-6.346q0-.463-.297-.76-.298-.298-.761-.298H14.04q-.463 0-.761.298-.298.297-.298.76v6.346q0 .462.298.76.298.297.76.297h10.589q.463 0 .76-.297.298-.298.298-.76zm16.94 12.691v-6.346q0-.462-.297-.76-.298-.297-.761-.297H30.98q-.463 0-.76.297-.299.298-.299.76v6.346q0 .463.298.76.298.298.761.298h10.588q.463 0 .76-.298.299-.297.299-.76zm-16.94-25.383v-6.345q0-.463-.297-.76-.298-.298-.761-.298H14.04q-.463 0-.761.297-.298.298-.298.76v6.346q0 .463.298.76.298.298.76.298h10.589q.463 0 .76-.298.298-.297.298-.76zm16.94 12.692v-6.346q0-.463-.297-.76-.298-.298-.761-.298H30.98q-.463 0-.76.298-.299.297-.299.76v6.346q0 .462.298.76.298.297.761.297h10.588q.463 0 .76-.297.299-.298.299-.76zm16.94 12.691v-6.346q0-.462-.297-.76-.298-.297-.76-.297H47.92q-.463 0-.76.297-.298.298-.298.76v6.346q0 .463.297.76.298.298.761.298h10.588q.463 0 .761-.298.298-.297.298-.76zm-16.94-25.383v-6.345q0-.463-.297-.76-.298-.298-.761-.298H30.98q-.463 0-.76.297-.299.298-.299.76v6.346q0 .463.298.76.298.298.761.298h10.588q.463 0 .76-.298.299-.297.299-.76zm16.94 12.692v-6.346q0-.463-.297-.76-.298-.298-.76-.298H47.92q-.463 0-.76.298-.298.297-.298.76v6.346q0 .462.297.76.298.297.761.297h10.588q.463 0 .761-.297.298-.298.298-.76zm0-12.692v-6.345q0-.463-.297-.76-.298-.298-.76-.298H47.92q-.463 0-.76.297-.298.298-.298.76v6.346q0 .463.297.76.298.298.761.298h10.588q.463 0 .761-.298.298-.297.298-.76zm4.236-10.576v35.96q0 2.18-1.555 3.734-1.555 1.553-3.739 1.553H14.04q-2.184 0-3.739-1.553-1.555-1.553-1.555-3.735V15.42q0-2.181 1.555-3.735 1.555-1.553 3.739-1.553h44.468q2.184 0 3.739 1.553 1.555 1.554 1.555 3.735z"/></symbol><symbol id="trumbowyg-underline" viewBox="0 0 72 72"><path d="M36 35zM15.2 55.9h41.6V59H15.2zM21.1 13.9h6.4v21.2c0 1.2.1 2.5.2 3.7.1 1.3.5 2.4 1 3.4.6 1 1.4 1.8 2.6 2.5 1.1.6 2.7 1 4.8 1 2.1 0 3.7-.3 4.8-1 1.1-.6 2-1.5 2.6-2.5.6-1 .9-2.1 1-3.4.1-1.3.2-2.5.2-3.7V13.9H51v23.3c0 2.3-.4 4.4-1.1 6.1-.7 1.7-1.7 3.2-3 4.4-1.3 1.2-2.9 2-4.7 2.6-1.8.6-3.9.9-6.1.9-2.2 0-4.3-.3-6.1-.9-1.8-.6-3.4-1.5-4.7-2.6-1.3-1.2-2.3-2.6-3-4.4-.7-1.7-1.1-3.8-1.1-6.1V13.9z"/></symbol><symbol id="trumbowyg-undo" viewBox="0 0 72 72"><path d="M61.2 51.2c0-5.1-2.1-9.7-5.4-13.1-3.3-3.3-8-5.4-13.1-5.4H26.1v-12L10.8 36l15.3 15.3V39.1h16.7c3.3 0 6.4 1.3 8.5 3.5 2.2 2.2 3.5 5.2 3.5 8.5h6.4z"/></symbol><symbol id="trumbowyg-unlink" viewBox="0 0 72 72"><path d="M30.9 49.1l-6.7 6.7c-.8.8-1.6.9-2.1.9s-1.4-.1-2.1-.9l-5.2-5.2c-1.1-1.1-1.1-3.1 0-4.2l6.1-6.1.2-.2 6.5-6.5c-1.2-.6-2.5-.9-3.8-.9-2.3 0-4.6.9-6.3 2.6L10.8 42c-3.5 3.5-3.5 9.2 0 12.7l5.2 5.2c1.7 1.7 4 2.6 6.3 2.6s4.6-.9 6.3-2.6l6.7-6.7C38 50.5 38.6 46.3 37 43l-6.1 6.1zM38.5 22.7l6.7-6.7c.8-.8 1.6-.9 2.1-.9s1.4.1 2.1.9l5.2 5.2c1.1 1.1 1.1 3.1 0 4.2l-6.1 6.1-.2.2-6.5 6.5c1.2.6 2.5.9 3.8.9 2.3 0 4.6-.9 6.3-2.6l6.7-6.7c3.5-3.5 3.5-9.2 0-12.7l-5.2-5.2c-1.7-1.7-4-2.6-6.3-2.6s-4.6.9-6.3 2.6l-6.7 6.7c-2.7 2.7-3.3 6.9-1.7 10.2l6.1-6.1z"/><path d="M44.1 30.7c.2-.2.4-.6.4-.9 0-.3-.1-.6-.4-.9l-2.3-2.3c-.2-.2-.6-.4-.9-.4-.3 0-.6.1-.9.4L25.8 40.8c-.2.2-.4.6-.4.9 0 .3.1.6.4.9l2.3 2.3c.2.2.6.4.9.4.3 0 .6-.1.9-.4l14.2-14.2zM41.3 55.8v-5h22.2v5H41.3z"/></symbol><symbol id="trumbowyg-unordered-list" viewBox="0 0 72 72"><path d="M27 14h36v8H27zM27 50h36v8H27zM9 50h9v8H9zM9 32h9v8H9zM9 14h9v8H9zM27 32h36v8H27z"/></symbol><symbol id="trumbowyg-view-html" viewBox="0 0 72 72"><path fill="none" stroke="currentColor" stroke-width="8" stroke-miterlimit="10" d="M26.9 17.9L9 36.2 26.9 54M45 54l17.9-18.3L45 17.9"/></symbol><symbol id="trumbowyg-base64" viewBox="0 0 72 72"><path d="M64 17v38H8V17h56m8-8H0v54h72V9z"/><path d="M29.9 28.9c-.5-.5-1.1-.8-1.8-.8s-1.4.2-1.9.7c-.5.4-.9 1-1.2 1.6-.3.6-.5 1.3-.6 2.1-.1.7-.2 1.4-.2 1.9l.1.1c.6-.8 1.2-1.4 2-1.8.8-.4 1.7-.5 2.7-.5.9 0 1.8.2 2.6.6.8.4 1.6.9 2.2 1.5.6.6 1 1.3 1.2 2.2.3.8.4 1.6.4 2.5 0 1.1-.2 2.1-.5 3-.3.9-.8 1.7-1.5 2.4-.6.7-1.4 1.2-2.3 1.6-.9.4-1.9.6-3 .6-1.6 0-2.8-.3-3.9-.9-1-.6-1.8-1.4-2.5-2.4-.6-1-1-2.1-1.3-3.4-.2-1.3-.4-2.6-.4-3.9 0-1.3.1-2.6.4-3.8.3-1.3.8-2.4 1.4-3.5.7-1 1.5-1.9 2.5-2.5 1-.6 2.3-1 3.8-1 .9 0 1.7.1 2.5.4.8.3 1.4.6 2 1.1.6.5 1.1 1.1 1.4 1.8.4.7.6 1.5.7 2.5h-4c0-1-.3-1.6-.8-2.1zm-3.5 6.8c-.4.2-.8.5-1 .8-.3.4-.5.8-.6 1.2-.1.5-.2 1-.2 1.5s.1.9.2 1.4c.1.5.4.9.6 1.2.3.4.6.7 1 .9.4.2.9.3 1.4.3.5 0 1-.1 1.3-.3.4-.2.7-.5 1-.9.3-.4.5-.8.6-1.2.1-.5.2-.9.2-1.4 0-.5-.1-1-.2-1.4-.1-.5-.3-.9-.6-1.2-.3-.4-.6-.7-1-.9-.4-.2-.9-.3-1.4-.3-.4 0-.9.1-1.3.3zM36.3 41.3v-3.8l9-12.1H49v12.4h2.7v3.5H49v4.8h-4v-4.8h-8.7zM45 30.7l-5.3 7.2h5.4l-.1-7.2z"/></symbol><symbol id="trumbowyg-back-color" viewBox="0 0 72 72"><path d="M36.5 22.3l-6.3 18.1H43l-6.3-18.1z"/><path d="M9 8.9v54.2h54.1V8.9H9zm39.9 48.2L45 46H28.2l-3.9 11.1h-7.6L32.8 15h7.8l16.2 42.1h-7.9z"/></symbol><symbol id="trumbowyg-fore-color" viewBox="0 0 72 72"><path d="M32 15h7.8L56 57.1h-7.9l-4-11.1H27.4l-4 11.1h-7.6L32 15zm-2.5 25.4h12.9L36 22.3h-.2l-6.3 18.1z"/></symbol><symbol id="trumbowyg-emoji" viewBox="0 0 72 72"><path d="M36.05 9C21.09 9 8.949 21.141 8.949 36.101c0 14.96 12.141 27.101 27.101 27.101 14.96 0 27.101-12.141 27.101-27.101S51.01 9 36.05 9zm9.757 15.095c2.651 0 4.418 1.767 4.418 4.418s-1.767 4.418-4.418 4.418-4.418-1.767-4.418-4.418 1.767-4.418 4.418-4.418zm-19.479 0c2.651 0 4.418 1.767 4.418 4.418s-1.767 4.418-4.418 4.418-4.418-1.767-4.418-4.418 1.767-4.418 4.418-4.418zm9.722 30.436c-14.093 0-16.261-13.009-16.261-13.009h32.522S50.143 54.531 36.05 54.531z"/></symbol><symbol id="trumbowyg-insert-audio" viewBox="0 0 8 8"><path d="M3.344 0L2 2H0v4h2l1.344 2H4V0h-.656zM5 1v1c.152 0 .313.026.469.063H5.5c.86.215 1.5.995 1.5 1.938a1.99 1.99 0 0 1-2 2.001v1a2.988 2.988 0 0 0 3-3 2.988 2.988 0 0 0-3-3zm0 2v2l.25-.031C5.683 4.851 6 4.462 6 4c0-.446-.325-.819-.75-.938v-.031h-.031L5 3z"/></symbol><symbol id="trumbowyg-mathml" viewBox="0 0 445.878 445.878"><path d="M426.024 86.447H209.705l-84.911 298.911c-2.568 7.967-9.854 13.482-18.22 13.771-.236 0-.464.006-.688.006a19.868 19.868 0 0 1-18.436-12.478l-34.714-86.782H19.851C8.884 299.876 0 290.986 0 280.022c0-10.965 8.893-19.854 19.851-19.854H66.18a19.862 19.862 0 0 1 18.436 12.483l19.237 48.09 72.472-260.218a19.855 19.855 0 0 1 18.903-13.781h230.798c10.97 0 19.854 8.89 19.854 19.851s-8.892 19.854-19.856 19.854zm10.699 266.78l-78.259-87.904 74.576-82.783c1.318-1.454 1.638-3.547.857-5.341a4.977 4.977 0 0 0-4.54-2.946h-47.18a4.995 4.995 0 0 0-3.759 1.72l-50.059 58.047-49.674-58.029a4.95 4.95 0 0 0-3.771-1.738H225.58a4.947 4.947 0 0 0-4.521 2.929 4.939 4.939 0 0 0 .824 5.332l73.743 82.81-77.641 87.923a4.977 4.977 0 0 0-.813 5.325 4.978 4.978 0 0 0 4.528 2.92h48.9c1.472 0 2.867-.65 3.807-1.785l51.819-62.181 53.05 62.229a4.972 4.972 0 0 0 3.782 1.743h49.97a4.938 4.938 0 0 0 4.527-2.926 4.966 4.966 0 0 0-.832-5.345z"/></symbol><symbol id="trumbowyg-mention" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M73.309 62.5c-1.53 9.86-8.16 17.85-14.45 17.85-5.61 0-8.5-4.08-8.5-10.54 0-13.089 8.84-24.139 20.06-24.139 2.21 0 3.91.34 5.27.68L73.309 62.5zm14.45 44.2c-6.8 3.57-15.98 5.44-24.65 5.44-25.329 0-43.519-16.15-43.519-44.54 0-32.469 22.78-52.869 48.789-52.869 26.35 0 40.63 17.17 40.63 39.27 0 19.549-9.18 28.899-16.49 28.729-4.76-.17-5.95-4.76-4.25-14.79l5.1-31.449c-4.25-2.38-12.75-4.25-20.23-4.25-24.48 0-39.779 18.87-39.779 39.609 0 13.94 7.99 22.1 19.039 22.1 9.01 0 16.66-4.42 21.93-13.09h.34c.85 9.01 6.63 13.09 14.62 13.09 18.36 0 32.3-15.64 32.3-40.459 0-28.56-21.42-49.13-51.34-49.13C31.83 4.361 6.67 34.451 6.67 69.13c0 33.32 24.82 53.55 53.039 53.55 12.07 0 20.91-1.53 31.11-6.12l-3.06-9.86z"/></symbol><symbol id="trumbowyg-noembed" viewBox="0 0 72 72"><path d="M31.5 33.6V25l11 11-11 11v-8.8z"/><path d="M64 17v38H8V17h56m8-8H0v54h72V9z"/></symbol><symbol id="trumbowyg-preformatted" viewBox="0 0 72 72"><path d="M10.3 33.5c.4 0 .9-.1 1.5-.2s1.2-.3 1.8-.7c.6-.3 1.1-.8 1.5-1.3.4-.5.6-1.3.6-2.1V17.1c0-1.4.3-2.6.8-3.6s1.2-1.9 2-2.5c.8-.7 1.6-1.2 2.5-1.5.9-.3 1.6-.5 2.2-.5h5.3v5.3h-3.2c-.7 0-1.3.1-1.8.4-.4.3-.8.6-1 1-.2.4-.4.9-.4 1.3-.1.5-.1.9-.1 1.4v11.4c0 1.2-.2 2.1-.7 2.9-.5.8-1 1.4-1.7 1.8-.6.4-1.3.8-2 1-.7.2-1.3.3-1.7.4v.1c.5 0 1 .1 1.7.3.7.2 1.3.5 2 .9.6.5 1.2 1.1 1.7 1.9.5.8.7 2 .7 3.4v11.1c0 .4 0 .9.1 1.4.1.5.2.9.4 1.3s.6.7 1 1c.4.3 1 .4 1.8.4h3.2V63h-5.3c-.6 0-1.4-.2-2.2-.5-.9-.3-1.7-.8-2.5-1.5s-1.4-1.5-2-2.5c-.5-1-.8-2.2-.8-3.6V43.5c0-.9-.2-1.7-.6-2.3-.4-.6-.9-1.1-1.5-1.5-.6-.4-1.2-.6-1.8-.7-.6-.1-1.1-.2-1.5-.2v-5.3zM61.8 38.7c-.4 0-1 .1-1.6.2-.6.1-1.2.4-1.8.7-.6.3-1.1.7-1.5 1.3-.4.5-.6 1.3-.6 2.1v12.1c0 1.4-.3 2.6-.8 3.6s-1.2 1.9-2 2.5c-.8.7-1.6 1.2-2.5 1.5-.9.3-1.6.5-2.2.5h-5.3v-5.3h3.2c.7 0 1.3-.1 1.8-.4.4-.3.8-.6 1-1 .2-.4.4-.9.4-1.3.1-.5.1-.9.1-1.4V42.3c0-1.2.2-2.1.7-2.9.5-.8 1-1.4 1.7-1.8.6-.4 1.3-.8 2-1 .7-.2 1.3-.3 1.7-.4v-.1c-.5 0-1-.1-1.7-.3-.7-.2-1.3-.5-2-.9-.6-.4-1.2-1.1-1.7-1.9-.5-.8-.7-2-.7-3.4V18.5c0-.4 0-.9-.1-1.4-.1-.5-.2-.9-.4-1.3s-.6-.7-1-1c-.4-.3-1-.4-1.8-.4h-3.2V9.1h5.3c.6 0 1.4.2 2.2.5.9.3 1.7.8 2.5 1.5s1.4 1.5 2 2.5c.5 1 .8 2.2.8 3.6v11.6c0 .9.2 1.7.6 2.3.4.6.9 1.1 1.5 1.5.6.4 1.2.6 1.8.7.6.1 1.2.2 1.6.2v5.2z"/></symbol><symbol id="trumbowyg-ruby" viewBox="0 0 72 72"><path d="M16.499 24.477h8.018L41.08 67.5H33l-4.04-11.361H11.804L7.764 67.5H0l16.499-43.023zm-2.65 25.907h13.127l-6.438-18.497h-.177l-6.512 18.497zM65.053 16.685c-6.316 1.178-12.025 1.98-17.126 2.408a362.385 362.385 0 0 0-.965 5.833c-.25 1.57-.679 3.907-1.286 7.013 3.033-1.963 5.852-3.266 8.458-3.907 2.639-.642 4.905-.891 6.797-.75 1.891.108 3.746.661 5.566 1.661 1.82.964 3.264 2.408 4.334 4.334 1.104 1.893 1.427 4.088.965 6.584-.466 2.461-1.554 4.494-3.265 6.101-1.679 1.605-3.658 2.783-5.941 3.532-2.283.785-4.853 1.251-7.707 1.391-2.819.144-5.906.161-9.259.056 0-1.642-.287-3.212-.857-4.71l.108-.59c2.711.5 5.246.768 7.601.802 2.39 0 4.529-.195 6.421-.589 1.927-.393 3.605-1.069 5.031-2.031 1.427-.965 2.319-2.319 2.676-4.067.394-1.75.269-3.229-.373-4.443-.644-1.249-1.446-2.213-2.408-2.891-.929-.68-2.161-1.034-3.693-1.071-1.536-.072-3.265.089-5.192.482-1.927.391-3.82 1.14-5.672 2.248a24.308 24.308 0 0 0-4.978 3.907l-4.872-1.981c1.463-5.031 2.355-8.597 2.677-10.703.321-2.105.642-4.067.963-5.887-3.961.25-7.154.411-9.58.481-.215-1.927-.52-3.534-.91-4.817l.32-.32c3.604.32 7.225.446 10.865.375.214-1.355.481-3.103.804-5.245.354-2.175.407-3.621.16-4.336.034-.784.374-1.017 1.017-.695l5.085.749c.428.251.444.573.055.964l-.857.91c-.537 2.89-.981 5.352-1.338 7.385 4.279-.427 9.312-1.393 15.092-2.89l1.284 4.707"/></symbol><symbol id="trumbowyg-upload" viewBox="0 0 72 72"><path d="M64 27v28H8V27H0v36h72V27h-8z"/><path d="M32.1 6.7h8v33.6h-8z"/><path d="M48 35.9L36 49.6 24 36h24z"/></symbol></svg>
\ No newline at end of file
public/javascripts/app.js +5 -1
@@ @@ -1,6 +1,7 @@
+ //= require vendor/autosize
+ //= require vendor/foundation
//= require vendor/jquery.sticky
//= require vendor/what-input
- //= require vendor/foundation
$(document).foundation();
// $(".top-bar").sticky({zIndex:10});
@@ @@ -11,3 +12,6 @@ $('nav#top-nav > ul ul').addClass('menu')
$('header[data-background-url]').each(function() {
$(this).css('background-image', 'url("' + $(this).data('background-url') + '")')
})
+
+ autosize($('textarea.autosize'));
+
public/javascripts/vendor/autosize.js +292 -0
@@ @@ -0,0 +1,292 @@
+ /*!
+ Autosize 4.0.0
+ license: MIT
+ http://www.jacklmoore.com/autosize
+ */
+ (function (global, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(['exports', 'module'], factory);
+ } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
+ factory(exports, module);
+ } else {
+ var mod = {
+ exports: {}
+ };
+ factory(mod.exports, mod);
+ global.autosize = mod.exports;
+ }
+ })(this, function (exports, module) {
+ 'use strict';
+
+ var map = typeof Map === "function" ? new Map() : (function () {
+ var keys = [];
+ var values = [];
+
+ return {
+ has: function has(key) {
+ return keys.indexOf(key) > -1;
+ },
+ get: function get(key) {
+ return values[keys.indexOf(key)];
+ },
+ set: function set(key, value) {
+ if (keys.indexOf(key) === -1) {
+ keys.push(key);
+ values.push(value);
+ }
+ },
+ 'delete': function _delete(key) {
+ var index = keys.indexOf(key);
+ if (index > -1) {
+ keys.splice(index, 1);
+ values.splice(index, 1);
+ }
+ }
+ };
+ })();
+
+ var createEvent = function createEvent(name) {
+ return new Event(name, { bubbles: true });
+ };
+ try {
+ new Event('test');
+ } catch (e) {
+ // IE does not support `new Event()`
+ createEvent = function (name) {
+ var evt = document.createEvent('Event');
+ evt.initEvent(name, true, false);
+ return evt;
+ };
+ }
+
+ function assign(ta) {
+ if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) return;
+
+ var heightOffset = null;
+ var clientWidth = ta.clientWidth;
+ var cachedHeight = null;
+
+ function init() {
+ var style = window.getComputedStyle(ta, null);
+
+ if (style.resize === 'vertical') {
+ ta.style.resize = 'none';
+ } else if (style.resize === 'both') {
+ ta.style.resize = 'horizontal';
+ }
+
+ if (style.boxSizing === 'content-box') {
+ heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
+ } else {
+ heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
+ }
+ // Fix when a textarea is not on document body and heightOffset is Not a Number
+ if (isNaN(heightOffset)) {
+ heightOffset = 0;
+ }
+
+ update();
+ }
+
+ function changeOverflow(value) {
+ {
+ // Chrome/Safari-specific fix:
+ // When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
+ // made available by removing the scrollbar. The following forces the necessary text reflow.
+ var width = ta.style.width;
+ ta.style.width = '0px';
+ // Force reflow:
+ /* jshint ignore:start */
+ ta.offsetWidth;
+ /* jshint ignore:end */
+ ta.style.width = width;
+ }
+
+ ta.style.overflowY = value;
+ }
+
+ function getParentOverflows(el) {
+ var arr = [];
+
+ while (el && el.parentNode && el.parentNode instanceof Element) {
+ if (el.parentNode.scrollTop) {
+ arr.push({
+ node: el.parentNode,
+ scrollTop: el.parentNode.scrollTop
+ });
+ }
+ el = el.parentNode;
+ }
+
+ return arr;
+ }
+
+ function resize() {
+ var originalHeight = ta.style.height;
+ var overflows = getParentOverflows(ta);
+ var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)
+
+ ta.style.height = '';
+
+ var endHeight = ta.scrollHeight + heightOffset;
+
+ if (ta.scrollHeight === 0) {
+ // If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
+ ta.style.height = originalHeight;
+ return;
+ }
+
+ ta.style.height = endHeight + 'px';
+
+ // used to check if an update is actually necessary on window.resize
+ clientWidth = ta.clientWidth;
+
+ // prevents scroll-position jumping
+ overflows.forEach(function (el) {
+ el.node.scrollTop = el.scrollTop;
+ });
+
+ if (docTop) {
+ document.documentElement.scrollTop = docTop;
+ }
+ }
+
+ function update() {
+ resize();
+
+ var styleHeight = Math.round(parseFloat(ta.style.height));
+ var computed = window.getComputedStyle(ta, null);
+
+ // Using offsetHeight as a replacement for computed.height in IE, because IE does not account use of border-box
+ var actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(computed.height)) : ta.offsetHeight;
+
+ // The actual height not matching the style height (set via the resize method) indicates that
+ // the max-height has been exceeded, in which case the overflow should be allowed.
+ if (actualHeight !== styleHeight) {
+ if (computed.overflowY === 'hidden') {
+ changeOverflow('scroll');
+ resize();
+ actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
+ }
+ } else {
+ // Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
+ if (computed.overflowY !== 'hidden') {
+ changeOverflow('hidden');
+ resize();
+ actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
+ }
+ }
+
+ if (cachedHeight !== actualHeight) {
+ cachedHeight = actualHeight;
+ var evt = createEvent('autosize:resized');
+ try {
+ ta.dispatchEvent(evt);
+ } catch (err) {
+ // Firefox will throw an error on dispatchEvent for a detached element
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=889376
+ }
+ }
+ }
+
+ var pageResize = function pageResize() {
+ if (ta.clientWidth !== clientWidth) {
+ update();
+ }
+ };
+
+ var destroy = (function (style) {
+ window.removeEventListener('resize', pageResize, false);
+ ta.removeEventListener('input', update, false);
+ ta.removeEventListener('keyup', update, false);
+ ta.removeEventListener('autosize:destroy', destroy, false);
+ ta.removeEventListener('autosize:update', update, false);
+
+ Object.keys(style).forEach(function (key) {
+ ta.style[key] = style[key];
+ });
+
+ map['delete'](ta);
+ }).bind(ta, {
+ height: ta.style.height,
+ resize: ta.style.resize,
+ overflowY: ta.style.overflowY,
+ overflowX: ta.style.overflowX,
+ wordWrap: ta.style.wordWrap
+ });
+
+ ta.addEventListener('autosize:destroy', destroy, false);
+
+ // IE9 does not fire onpropertychange or oninput for deletions,
+ // so binding to onkeyup to catch most of those events.
+ // There is no way that I know of to detect something like 'cut' in IE9.
+ if ('onpropertychange' in ta && 'oninput' in ta) {
+ ta.addEventListener('keyup', update, false);
+ }
+
+ window.addEventListener('resize', pageResize, false);
+ ta.addEventListener('input', update, false);
+ ta.addEventListener('autosize:update', update, false);
+ ta.style.overflowX = 'hidden';
+ ta.style.wordWrap = 'break-word';
+
+ map.set(ta, {
+ destroy: destroy,
+ update: update
+ });
+
+ init();
+ }
+
+ function destroy(ta) {
+ var methods = map.get(ta);
+ if (methods) {
+ methods.destroy();
+ }
+ }
+
+ function update(ta) {
+ var methods = map.get(ta);
+ if (methods) {
+ methods.update();
+ }
+ }
+
+ var autosize = null;
+
+ // Do nothing in Node.js environment and IE8 (or lower)
+ if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
+ autosize = function (el) {
+ return el;
+ };
+ autosize.destroy = function (el) {
+ return el;
+ };
+ autosize.update = function (el) {
+ return el;
+ };
+ } else {
+ autosize = function (el, options) {
+ if (el) {
+ Array.prototype.forEach.call(el.length ? el : [el], function (x) {
+ return assign(x, options);
+ });
+ }
+ return el;
+ };
+ autosize.destroy = function (el) {
+ if (el) {
+ Array.prototype.forEach.call(el.length ? el : [el], destroy);
+ }
+ return el;
+ };
+ autosize.update = function (el) {
+ if (el) {
+ Array.prototype.forEach.call(el.length ? el : [el], update);
+ }
+ return el;
+ };
+ }
+
+ module.exports = autosize;
+ });
\ No newline at end of file
public/javascripts/vendor/trumbowyg.js +1738 -0
@@ @@ -0,0 +1,1738 @@
+ /**
+ * Trumbowyg v2.9.4 - A lightweight WYSIWYG editor
+ * Trumbowyg core file
+ * ------------------------
+ * @link http://alex-d.github.io/Trumbowyg
+ * @license MIT
+ * @author Alexandre Demode (Alex-D)
+ * Twitter : @AlexandreDemode
+ * Website : alex-d.fr
+ */
+
+ jQuery.trumbowyg = {
+ langs: {
+ en: {
+ viewHTML: 'View HTML',
+
+ undo: 'Undo',
+ redo: 'Redo',
+
+ formatting: 'Formatting',
+ p: 'Paragraph',
+ blockquote: 'Quote',
+ code: 'Code',
+ header: 'Header',
+
+ bold: 'Bold',
+ italic: 'Italic',
+ strikethrough: 'Stroke',
+ underline: 'Underline',
+
+ strong: 'Strong',
+ em: 'Emphasis',
+ del: 'Deleted',
+
+ superscript: 'Superscript',
+ subscript: 'Subscript',
+
+ unorderedList: 'Unordered list',
+ orderedList: 'Ordered list',
+
+ insertImage: 'Insert Image',
+ link: 'Link',
+ createLink: 'Insert link',
+ unlink: 'Remove link',
+
+ justifyLeft: 'Align Left',
+ justifyCenter: 'Align Center',
+ justifyRight: 'Align Right',
+ justifyFull: 'Align Justify',
+
+ horizontalRule: 'Insert horizontal rule',
+ removeformat: 'Remove format',
+
+ fullscreen: 'Fullscreen',
+
+ close: 'Close',
+
+ submit: 'Confirm',
+ reset: 'Cancel',
+
+ required: 'Required',
+ description: 'Description',
+ title: 'Title',
+ text: 'Text',
+ target: 'Target',
+ width: 'Width'
+ }
+ },
+
+ // Plugins
+ plugins: {},
+
+ // SVG Path globally
+ svgPath: null,
+
+ hideButtonTexts: null
+ };
+
+ // Makes default options read-only
+ Object.defineProperty(jQuery.trumbowyg, 'defaultOptions', {
+ value: {
+ lang: 'en',
+
+ fixedBtnPane: false,
+ fixedFullWidth: false,
+ autogrow: false,
+ autogrowOnEnter: false,
+ imageWidthModalEdit: false,
+
+ prefix: 'trumbowyg-',
+
+ semantic: true,
+ resetCss: false,
+ removeformatPasted: false,
+ tagsToRemove: [],
+ btns: [
+ ['viewHTML'],
+ ['undo', 'redo'], // Only supported in Blink browsers
+ ['formatting'],
+ ['strong', 'em', 'del'],
+ ['superscript', 'subscript'],
+ ['link'],
+ ['insertImage'],
+ ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
+ ['unorderedList', 'orderedList'],
+ ['horizontalRule'],
+ ['removeformat'],
+ ['fullscreen']
+ ],
+ // For custom button definitions
+ btnsDef: {},
+
+ inlineElementsSelector: 'a,abbr,acronym,b,caption,cite,code,col,dfn,dir,dt,dd,em,font,hr,i,kbd,li,q,span,strikeout,strong,sub,sup,u',
+
+ pasteHandlers: [],
+
+ // imgDblClickHandler: default is defined in constructor
+
+ plugins: {}
+ },
+ writable: false,
+ enumerable: true,
+ configurable: false
+ });
+
+
+ (function (navigator, window, document, $) {
+ 'use strict';
+
+ var CONFIRM_EVENT = 'tbwconfirm',
+ CANCEL_EVENT = 'tbwcancel';
+
+ $.fn.trumbowyg = function (options, params) {
+ var trumbowygDataName = 'trumbowyg';
+ if (options === Object(options) || !options) {
+ return this.each(function () {
+ if (!$(this).data(trumbowygDataName)) {
+ $(this).data(trumbowygDataName, new Trumbowyg(this, options));
+ }
+ });
+ }
+ if (this.length === 1) {
+ try {
+ var t = $(this).data(trumbowygDataName);
+ switch (options) {
+ // Exec command
+ case 'execCmd':
+ return t.execCmd(params.cmd, params.param, params.forceCss);
+
+ // Modal box
+ case 'openModal':
+ return t.openModal(params.title, params.content);
+ case 'closeModal':
+ return t.closeModal();
+ case 'openModalInsert':
+ return t.openModalInsert(params.title, params.fields, params.callback);
+
+ // Range
+ case 'saveRange':
+ return t.saveRange();
+ case 'getRange':
+ return t.range;
+ case 'getRangeText':
+ return t.getRangeText();
+ case 'restoreRange':
+ return t.restoreRange();
+
+ // Enable/disable
+ case 'enable':
+ return t.setDisabled(false);
+ case 'disable':
+ return t.setDisabled(true);
+
+ // Toggle
+ case 'toggle':
+ return t.toggle();
+
+ // Destroy
+ case 'destroy':
+ return t.destroy();
+
+ // Empty
+ case 'empty':
+ return t.empty();
+
+ // HTML
+ case 'html':
+ return t.html(params);
+ }
+ } catch (c) {
+ }
+ }
+
+ return false;
+ };
+
+ // @param: editorElem is the DOM element
+ var Trumbowyg = function (editorElem, options) {
+ var t = this,
+ trumbowygIconsId = 'trumbowyg-icons',
+ $trumbowyg = $.trumbowyg;
+
+ // Get the document of the element. It use to makes the plugin
+ // compatible on iframes.
+ t.doc = editorElem.ownerDocument || document;
+
+ // jQuery object of the editor
+ t.$ta = $(editorElem); // $ta : Textarea
+ t.$c = $(editorElem); // $c : creator
+
+ options = options || {};
+
+ // Localization management
+ if (options.lang != null || $trumbowyg.langs[options.lang] != null) {
+ t.lang = $.extend(true, {}, $trumbowyg.langs.en, $trumbowyg.langs[options.lang]);
+ } else {
+ t.lang = $trumbowyg.langs.en;
+ }
+
+ t.hideButtonTexts = $trumbowyg.hideButtonTexts != null ? $trumbowyg.hideButtonTexts : options.hideButtonTexts;
+
+ // SVG path
+ var svgPathOption = $trumbowyg.svgPath != null ? $trumbowyg.svgPath : options.svgPath;
+ t.hasSvg = svgPathOption !== false;
+ t.svgPath = !!t.doc.querySelector('base') ? window.location.href.split('#')[0] : '';
+ if ($('#' + trumbowygIconsId, t.doc).length === 0 && svgPathOption !== false) {
+ if (svgPathOption == null) {
+ // Hack to get svgPathOption based on trumbowyg.js path
+ var scriptElements = document.getElementsByTagName('script');
+ for (var i = 0; i < scriptElements.length; i += 1) {
+ var source = scriptElements[i].src;
+ var matches = source.match('trumbowyg(\.min)?\.js');
+ if (matches != null) {
+ svgPathOption = source.substring(0, source.indexOf(matches[0])) + '/ui/icons.svg';
+ }
+ }
+ if (svgPathOption == null) {
+ console.warn('You must define svgPath: https://goo.gl/CfTY9U'); // jshint ignore:line
+ }
+ }
+
+ var div = t.doc.createElement('div');
+ div.id = trumbowygIconsId;
+ t.doc.body.insertBefore(div, t.doc.body.childNodes[0]);
+ $.ajax({
+ async: true,
+ type: 'GET',
+ contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
+ dataType: 'xml',
+ crossDomain: true,
+ url: svgPathOption,
+ data: null,
+ beforeSend: null,
+ complete: null,
+ success: function (data) {
+ div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
+ }
+ });
+ }
+
+
+ /**
+ * When the button is associated to a empty object
+ * fn and title attributs are defined from the button key value
+ *
+ * For example
+ * foo: {}
+ * is equivalent to :
+ * foo: {
+ * fn: 'foo',
+ * title: this.lang.foo
+ * }
+ */
+ var h = t.lang.header, // Header translation
+ isBlinkFunction = function () {
+ return (window.chrome || (window.Intl && Intl.v8BreakIterator)) && 'CSS' in window;
+ };
+ t.btnsDef = {
+ viewHTML: {
+ fn: 'toggle'
+ },
+
+ undo: {
+ isSupported: isBlinkFunction,
+ key: 'Z'
+ },
+ redo: {
+ isSupported: isBlinkFunction,
+ key: 'Y'
+ },
+
+ p: {
+ fn: 'formatBlock'
+ },
+ blockquote: {
+ fn: 'formatBlock'
+ },
+ h1: {
+ fn: 'formatBlock',
+ title: h + ' 1'
+ },
+ h2: {
+ fn: 'formatBlock',
+ title: h + ' 2'
+ },
+ h3: {
+ fn: 'formatBlock',
+ title: h + ' 3'
+ },
+ h4: {
+ fn: 'formatBlock',
+ title: h + ' 4'
+ },
+ subscript: {
+ tag: 'sub'
+ },
+ superscript: {
+ tag: 'sup'
+ },
+
+ bold: {
+ key: 'B',
+ tag: 'b'
+ },
+ italic: {
+ key: 'I',
+ tag: 'i'
+ },
+ underline: {
+ tag: 'u'
+ },
+ strikethrough: {
+ tag: 'strike'
+ },
+
+ strong: {
+ fn: 'bold',
+ key: 'B'
+ },
+ em: {
+ fn: 'italic',
+ key: 'I'
+ },
+ del: {
+ fn: 'strikethrough'
+ },
+
+ createLink: {
+ key: 'K',
+ tag: 'a'
+ },
+ unlink: {},
+
+ insertImage: {},
+
+ justifyLeft: {
+ tag: 'left',
+ forceCss: true
+ },
+ justifyCenter: {
+ tag: 'center',
+ forceCss: true
+ },
+ justifyRight: {
+ tag: 'right',
+ forceCss: true
+ },
+ justifyFull: {
+ tag: 'justify',
+ forceCss: true
+ },
+
+ unorderedList: {
+ fn: 'insertUnorderedList',
+ tag: 'ul'
+ },
+ orderedList: {
+ fn: 'insertOrderedList',
+ tag: 'ol'
+ },
+
+ horizontalRule: {
+ fn: 'insertHorizontalRule'
+ },
+
+ removeformat: {},
+
+ fullscreen: {
+ class: 'trumbowyg-not-disable'
+ },
+ close: {
+ fn: 'destroy',
+ class: 'trumbowyg-not-disable'
+ },
+
+ // Dropdowns
+ formatting: {
+ dropdown: ['p', 'blockquote', 'h1', 'h2', 'h3', 'h4'],
+ ico: 'p'
+ },
+ link: {
+ dropdown: ['createLink', 'unlink']
+ }
+ };
+
+ // Defaults Options
+ t.o = $.extend(true, {}, $trumbowyg.defaultOptions, options);
+ if (!t.o.hasOwnProperty('imgDblClickHandler')) {
+ t.o.imgDblClickHandler = t.getDefaultImgDblClickHandler();
+ }
+
+ t.disabled = t.o.disabled || (editorElem.nodeName === 'TEXTAREA' && editorElem.disabled);
+
+ if (options.btns) {
+ t.o.btns = options.btns;
+ } else if (!t.o.semantic) {
+ t.o.btns[3] = ['bold', 'italic', 'underline', 'strikethrough'];
+ }
+
+ $.each(t.o.btnsDef, function (btnName, btnDef) {
+ t.addBtnDef(btnName, btnDef);
+ });
+
+ // put this here in the event it would be merged in with options
+ t.eventNamespace = 'trumbowyg-event';
+
+ // Keyboard shortcuts are load in this array
+ t.keys = [];
+
+ // Tag to button dynamically hydrated
+ t.tagToButton = {};
+ t.tagHandlers = [];
+
+ // Admit multiple paste handlers
+ t.pasteHandlers = [].concat(t.o.pasteHandlers);
+
+ // Check if browser is IE
+ t.isIE = (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') !== -1);
+
+ t.init();
+ };
+
+ Trumbowyg.prototype = {
+ init: function () {
+ var t = this;
+ t.height = t.$ta.height();
+
+ t.initPlugins();
+
+ try {
+ // Disable image resize, try-catch for old IE
+ t.doc.execCommand('enableObjectResizing', false, false);
+ t.doc.execCommand('defaultParagraphSeparator', false, 'p');
+ } catch (e) {
+ }
+
+ t.buildEditor();
+ t.buildBtnPane();
+
+ t.fixedBtnPaneEvents();
+
+ t.buildOverlay();
+
+ setTimeout(function () {
+ if (t.disabled) {
+ t.setDisabled(true);
+ }
+ t.$c.trigger('tbwinit');
+ });
+ },
+
+ addBtnDef: function (btnName, btnDef) {
+ this.btnsDef[btnName] = btnDef;
+ },
+
+ buildEditor: function () {
+ var t = this,
+ prefix = t.o.prefix,
+ html = '';
+
+ t.$box = $('<div/>', {
+ class: prefix + 'box ' + prefix + 'editor-visible ' + prefix + t.o.lang + ' trumbowyg'
+ });
+
+ // $ta = Textarea
+ // $ed = Editor
+ t.isTextarea = t.$ta.is('textarea');
+ if (t.isTextarea) {
+ html = t.$ta.val();
+ t.$ed = $('<div/>');
+ t.$box
+ .insertAfter(t.$ta)
+ .append(t.$ed, t.$ta);
+ } else {
+ t.$ed = t.$ta;
+ html = t.$ed.html();
+
+ t.$ta = $('<textarea/>', {
+ name: t.$ta.attr('id'),
+ height: t.height
+ }).val(html);
+
+ t.$box
+ .insertAfter(t.$ed)
+ .append(t.$ta, t.$ed);
+ t.syncCode();
+ }
+
+ t.$ta
+ .addClass(prefix + 'textarea')
+ .attr('tabindex', -1)
+ ;
+
+ t.$ed
+ .addClass(prefix + 'editor')
+ .attr({
+ contenteditable: true,
+ dir: t.lang._dir || 'ltr'
+ })
+ .html(html)
+ ;
+
+ if (t.o.tabindex) {
+ t.$ed.attr('tabindex', t.o.tabindex);
+ }
+
+ if (t.$c.is('[placeholder]')) {
+ t.$ed.attr('placeholder', t.$c.attr('placeholder'));
+ }
+
+ if (t.$c.is('[spellcheck]')) {
+ t.$ed.attr('spellcheck', t.$c.attr('spellcheck'));
+ }
+
+ if (t.o.resetCss) {
+ t.$ed.addClass(prefix + 'reset-css');
+ }
+
+ if (!t.o.autogrow) {
+ t.$ta.add(t.$ed).css({
+ height: t.height
+ });
+ }
+
+ t.semanticCode();
+
+ if (t.o.autogrowOnEnter) {
+ t.$ed.addClass(prefix + 'autogrow-on-enter');
+ }
+
+ var ctrl = false,
+ composition = false,
+ debounceButtonPaneStatus,
+ updateEventName = 'keyup';
+
+ t.$ed
+ .on('dblclick', 'img', t.o.imgDblClickHandler)
+ .on('keydown', function (e) {
+ if ((e.ctrlKey || e.metaKey) && !e.altKey) {
+ ctrl = true;
+ var key = t.keys[String.fromCharCode(e.which).toUpperCase()];
+
+ try {
+ t.execCmd(key.fn, key.param);
+ return false;
+ } catch (c) {
+ }
+ }
+ })
+ .on('compositionstart compositionupdate', function () {
+ composition = true;
+ })
+ .on(updateEventName + ' compositionend', function (e) {
+ if (e.type === 'compositionend') {
+ composition = false;
+ } else if (composition) {
+ return;
+ }
+
+ var keyCode = e.which;
+
+ if (keyCode >= 37 && keyCode <= 40) {
+ return;
+ }
+
+ if ((e.ctrlKey || e.metaKey) && (keyCode === 89 || keyCode === 90)) {
+ t.$c.trigger('tbwchange');
+ } else if (!ctrl && keyCode !== 17) {
+ var compositionend_ie = t.isIE ? e.type === 'compositionend' : true;
+ t.semanticCode(false, compositionend_ie && keyCode === 13);
+ t.$c.trigger('tbwchange');
+ } else if (typeof e.which === 'undefined') {
+ t.semanticCode(false, false, true);
+ }
+
+ setTimeout(function () {
+ ctrl = false;
+ }, 50);
+ })
+ .on('mouseup keydown keyup', function (e) {
+ if ((!e.ctrlKey && !e.metaKey) || e.altKey) {
+ setTimeout(function () { // "hold on" to the ctrl key for 50ms
+ ctrl = false;
+ }, 50);
+ }
+ clearTimeout(debounceButtonPaneStatus);
+ debounceButtonPaneStatus = setTimeout(function () {
+ t.updateButtonPaneStatus();
+ }, 50);
+ })
+ .on('focus blur', function (e) {
+ t.$c.trigger('tbw' + e.type);
+ if (e.type === 'blur') {
+ $('.' + prefix + 'active-button', t.$btnPane).removeClass(prefix + 'active-button ' + prefix + 'active');
+ }
+ if (t.o.autogrowOnEnter) {
+ if (t.autogrowOnEnterDontClose) {
+ return;
+ }
+ if (e.type === 'focus') {
+ t.autogrowOnEnterWasFocused = true;
+ t.autogrowEditorOnEnter();
+ }
+ else if (!t.o.autogrow) {
+ t.$ed.css({height: t.$ed.css('min-height')});
+ t.$c.trigger('tbwresize');
+ }
+ }
+ })
+ .on('cut', function () {
+ setTimeout(function () {
+ t.semanticCode(false, true);
+ t.$c.trigger('tbwchange');
+ }, 0);
+ })
+ .on('paste', function (e) {
+ if (t.o.removeformatPasted) {
+ e.preventDefault();
+
+ if (window.getSelection && window.getSelection().deleteFromDocument) {
+ window.getSelection().deleteFromDocument();
+ }
+
+ try {
+ // IE
+ var text = window.clipboardData.getData('Text');
+
+ try {
+ // <= IE10
+ t.doc.selection.createRange().pasteHTML(text);
+ } catch (c) {
+ // IE 11
+ t.doc.getSelection().getRangeAt(0).insertNode(t.doc.createTextNode(text));
+ }
+ t.$c.trigger('tbwchange', e);
+ } catch (d) {
+ // Not IE
+ t.execCmd('insertText', (e.originalEvent || e).clipboardData.getData('text/plain'));
+ }
+ }
+
+ // Call pasteHandlers
+ $.each(t.pasteHandlers, function (i, pasteHandler) {
+ pasteHandler(e);
+ });
+
+ setTimeout(function () {
+ t.semanticCode(false, true);
+ t.$c.trigger('tbwpaste', e);
+ }, 0);
+ });
+
+ t.$ta
+ .on('keyup', function () {
+ t.$c.trigger('tbwchange');
+ })
+ .on('paste', function () {
+ setTimeout(function () {
+ t.$c.trigger('tbwchange');
+ }, 0);
+ });
+
+ t.$box.on('keydown', function (e) {
+ if (e.which === 27 && $('.' + prefix + 'modal-box', t.$box).length === 1) {
+ t.closeModal();
+ return false;
+ }
+ });
+ },
+
+ //autogrow when entering logic
+ autogrowEditorOnEnter: function () {
+ var t = this;
+ t.$ed.removeClass('autogrow-on-enter');
+ var oldHeight = t.$ed[0].clientHeight;
+ t.$ed.height('auto');
+ var totalHeight = t.$ed[0].scrollHeight;
+ t.$ed.addClass('autogrow-on-enter');
+ if (oldHeight !== totalHeight) {
+ t.$ed.height(oldHeight);
+ setTimeout(function () {
+ t.$ed.css({height: totalHeight});
+ t.$c.trigger('tbwresize');
+ }, 0);
+ }
+ },
+
+
+ // Build button pane, use o.btns option
+ buildBtnPane: function () {
+ var t = this,
+ prefix = t.o.prefix;
+
+ var $btnPane = t.$btnPane = $('<div/>', {
+ class: prefix + 'button-pane'
+ });
+
+ $.each(t.o.btns, function (i, btnGrp) {
+ if (!$.isArray(btnGrp)) {
+ btnGrp = [btnGrp];
+ }
+
+ var $btnGroup = $('<div/>', {
+ class: prefix + 'button-group ' + ((btnGrp.indexOf('fullscreen') >= 0) ? prefix + 'right' : '')
+ });
+ $.each(btnGrp, function (i, btn) {
+ try { // Prevent buildBtn error
+ if (t.isSupportedBtn(btn)) { // It's a supported button
+ $btnGroup.append(t.buildBtn(btn));
+ }
+ } catch (c) {
+ }
+ });
+
+ if ($btnGroup.html().trim().length > 0) {
+ $btnPane.append($btnGroup);
+ }
+ });
+
+ t.$box.prepend($btnPane);
+ },
+
+
+ // Build a button and his action
+ buildBtn: function (btnName) { // btnName is name of the button
+ var t = this,
+ prefix = t.o.prefix,
+ btn = t.btnsDef[btnName],
+ isDropdown = btn.dropdown,
+ hasIcon = btn.hasIcon != null ? btn.hasIcon : true,
+ textDef = t.lang[btnName] || btnName,
+
+ $btn = $('<button/>', {
+ type: 'button',
+ class: prefix + btnName + '-button ' + (btn.class || '') + (!hasIcon ? ' ' + prefix + 'textual-button' : ''),
+ html: t.hasSvg && hasIcon ?
+ '<svg><use xlink:href="' + t.svgPath + '#' + prefix + (btn.ico || btnName).replace(/([A-Z]+)/g, '-$1').toLowerCase() + '"/></svg>' :
+ t.hideButtonTexts ? '' : (btn.text || btn.title || t.lang[btnName] || btnName),
+ title: (btn.title || btn.text || textDef) + ((btn.key) ? ' (Ctrl + ' + btn.key + ')' : ''),
+ tabindex: -1,
+ mousedown: function () {
+ if (!isDropdown || $('.' + btnName + '-' + prefix + 'dropdown', t.$box).is(':hidden')) {
+ $('body', t.doc).trigger('mousedown');
+ }
+
+ if ((t.$btnPane.hasClass(prefix + 'disable') || t.$box.hasClass(prefix + 'disabled')) &&
+ !$(this).hasClass(prefix + 'active') &&
+ !$(this).hasClass(prefix + 'not-disable')) {
+ return false;
+ }
+
+ t.execCmd((isDropdown ? 'dropdown' : false) || btn.fn || btnName, btn.param || btnName, btn.forceCss);
+
+ return false;
+ }
+ });
+
+ if (isDropdown) {
+ $btn.addClass(prefix + 'open-dropdown');
+ var dropdownPrefix = prefix + 'dropdown',
+ dropdownOptions = { // the dropdown
+ class: dropdownPrefix + '-' + btnName + ' ' + dropdownPrefix + ' ' + prefix + 'fixed-top'
+ };
+ dropdownOptions['data-' + dropdownPrefix] = btnName;
+ var $dropdown = $('<div/>', dropdownOptions);
+ $.each(isDropdown, function (i, def) {
+ if (t.btnsDef[def] && t.isSupportedBtn(def)) {
+ $dropdown.append(t.buildSubBtn(def));
+ }
+ });
+ t.$box.append($dropdown.hide());
+ } else if (btn.key) {
+ t.keys[btn.key] = {
+ fn: btn.fn || btnName,
+ param: btn.param || btnName
+ };
+ }
+
+ if (!isDropdown) {
+ t.tagToButton[(btn.tag || btnName).toLowerCase()] = btnName;
+ }
+
+ return $btn;
+ },
+ // Build a button for dropdown menu
+ // @param n : name of the subbutton
+ buildSubBtn: function (btnName) {
+ var t = this,
+ prefix = t.o.prefix,
+ btn = t.btnsDef[btnName],
+ hasIcon = btn.hasIcon != null ? btn.hasIcon : true;
+
+ if (btn.key) {
+ t.keys[btn.key] = {
+ fn: btn.fn || btnName,
+ param: btn.param || btnName
+ };
+ }
+
+ t.tagToButton[(btn.tag || btnName).toLowerCase()] = btnName;
+
+ return $('<button/>', {
+ type: 'button',
+ class: prefix + btnName + '-dropdown-button' + (btn.ico ? ' ' + prefix + btn.ico + '-button' : ''),
+ html: t.hasSvg && hasIcon ? '<svg><use xlink:href="' + t.svgPath + '#' + prefix + (btn.ico || btnName).replace(/([A-Z]+)/g, '-$1').toLowerCase() + '"/></svg>' + (btn.text || btn.title || t.lang[btnName] || btnName) : (btn.text || btn.title || t.lang[btnName] || btnName),
+ title: ((btn.key) ? ' (Ctrl + ' + btn.key + ')' : null),
+ style: btn.style || null,
+ mousedown: function () {
+ $('body', t.doc).trigger('mousedown');
+
+ t.execCmd(btn.fn || btnName, btn.param || btnName, btn.forceCss);
+
+ return false;
+ }
+ });
+ },
+ // Check if button is supported
+ isSupportedBtn: function (b) {
+ try {
+ return this.btnsDef[b].isSupported();
+ } catch (c) {
+ }
+ return true;
+ },
+
+ // Build overlay for modal box
+ buildOverlay: function () {
+ var t = this;
+ t.$overlay = $('<div/>', {
+ class: t.o.prefix + 'overlay'
+ }).appendTo(t.$box);
+ return t.$overlay;
+ },
+ showOverlay: function () {
+ var t = this;
+ $(window).trigger('scroll');
+ t.$overlay.fadeIn(200);
+ t.$box.addClass(t.o.prefix + 'box-blur');
+ },
+ hideOverlay: function () {
+ var t = this;
+ t.$overlay.fadeOut(50);
+ t.$box.removeClass(t.o.prefix + 'box-blur');
+ },
+
+ // Management of fixed button pane
+ fixedBtnPaneEvents: function () {
+ var t = this,
+ fixedFullWidth = t.o.fixedFullWidth,
+ $box = t.$box;
+
+ if (!t.o.fixedBtnPane) {
+ return;
+ }
+
+ t.isFixed = false;
+
+ $(window)
+ .on('scroll.' + t.eventNamespace + ' resize.' + t.eventNamespace, function () {
+ if (!$box) {
+ return;
+ }
+
+ t.syncCode();
+
+ var scrollTop = $(window).scrollTop(),
+ offset = $box.offset().top + 1,
+ bp = t.$btnPane,
+ oh = bp.outerHeight() - 2;
+
+ if ((scrollTop - offset > 0) && ((scrollTop - offset - t.height) < 0)) {
+ if (!t.isFixed) {
+ t.isFixed = true;
+ bp.css({
+ position: 'fixed',
+ top: 0,
+ left: fixedFullWidth ? '0' : 'auto',
+ zIndex: 7
+ });
+ $([t.$ta, t.$ed]).css({marginTop: bp.height()});
+ }
+ bp.css({
+ width: fixedFullWidth ? '100%' : (($box.width() - 1) + 'px')
+ });
+
+ $('.' + t.o.prefix + 'fixed-top', $box).css({
+ position: fixedFullWidth ? 'fixed' : 'absolute',
+ top: fixedFullWidth ? oh : oh + (scrollTop - offset) + 'px',
+ zIndex: 15
+ });
+ } else if (t.isFixed) {
+ t.isFixed = false;
+ bp.removeAttr('style');
+ $([t.$ta, t.$ed]).css({marginTop: 0});
+ $('.' + t.o.prefix + 'fixed-top', $box).css({
+ position: 'absolute',
+ top: oh
+ });
+ }
+ });
+ },
+
+ // Disable editor
+ setDisabled: function (disable) {
+ var t = this,
+ prefix = t.o.prefix;
+
+ t.disabled = disable;
+
+ if (disable) {
+ t.$ta.attr('disabled', true);
+ } else {
+ t.$ta.removeAttr('disabled');
+ }
+ t.$box.toggleClass(prefix + 'disabled', disable);
+ t.$ed.attr('contenteditable', !disable);
+ },
+
+ // Destroy the editor
+ destroy: function () {
+ var t = this,
+ prefix = t.o.prefix;
+
+ if (t.isTextarea) {
+ t.$box.after(
+ t.$ta
+ .css({height: ''})
+ .val(t.html())
+ .removeClass(prefix + 'textarea')
+ .show()
+ );
+ } else {
+ t.$box.after(
+ t.$ed
+ .css({height: ''})
+ .removeClass(prefix + 'editor')
+ .removeAttr('contenteditable')
+ .removeAttr('dir')
+ .html(t.html())
+ .show()
+ );
+ }
+
+ t.$ed.off('dblclick', 'img');
+
+ t.destroyPlugins();
+
+ t.$box.remove();
+ t.$c.removeData('trumbowyg');
+ $('body').removeClass(prefix + 'body-fullscreen');
+ t.$c.trigger('tbwclose');
+ $(window).off('scroll.' + t.eventNamespace + ' resize.' + t.eventNamespace);
+ },
+
+
+ // Empty the editor
+ empty: function () {
+ this.$ta.val('');
+ this.syncCode(true);
+ },
+
+
+ // Function call when click on viewHTML button
+ toggle: function () {
+ var t = this,
+ prefix = t.o.prefix;
+
+ if (t.o.autogrowOnEnter) {
+ t.autogrowOnEnterDontClose = !t.$box.hasClass(prefix + 'editor-hidden');
+ }
+
+ t.semanticCode(false, true);
+
+ setTimeout(function () {
+ t.doc.activeElement.blur();
+ t.$box.toggleClass(prefix + 'editor-hidden ' + prefix + 'editor-visible');
+ t.$btnPane.toggleClass(prefix + 'disable');
+ $('.' + prefix + 'viewHTML-button', t.$btnPane).toggleClass(prefix + 'active');
+ if (t.$box.hasClass(prefix + 'editor-visible')) {
+ t.$ta.attr('tabindex', -1);
+ } else {
+ t.$ta.removeAttr('tabindex');
+ }
+
+ if (t.o.autogrowOnEnter && !t.autogrowOnEnterDontClose) {
+ t.autogrowEditorOnEnter();
+ }
+ }, 0);
+ },
+
+ // Open dropdown when click on a button which open that
+ dropdown: function (name) {
+ var t = this,
+ d = t.doc,
+ prefix = t.o.prefix,
+ $dropdown = $('[data-' + prefix + 'dropdown=' + name + ']', t.$box),
+ $btn = $('.' + prefix + name + '-button', t.$btnPane),
+ show = $dropdown.is(':hidden');
+
+ $('body', d).trigger('mousedown');
+
+ if (show) {
+ var o = $btn.offset().left;
+ $btn.addClass(prefix + 'active');
+
+ $dropdown.css({
+ position: 'absolute',
+ top: $btn.offset().top - t.$btnPane.offset().top + $btn.outerHeight(),
+ left: (t.o.fixedFullWidth && t.isFixed) ? o + 'px' : (o - t.$btnPane.offset().left) + 'px'
+ }).show();
+
+ $(window).trigger('scroll');
+
+ $('body', d).on('mousedown.' + t.eventNamespace, function (e) {
+ if (!$dropdown.is(e.target)) {
+ $('.' + prefix + 'dropdown', t.$box).hide();
+ $('.' + prefix + 'active', t.$btnPane).removeClass(prefix + 'active');
+ $('body', d).off('mousedown.' + t.eventNamespace);
+ }
+ });
+ }
+ },
+
+
+ // HTML Code management
+ html: function (html) {
+ var t = this;
+ if (html != null) {
+ t.$ta.val(html);
+ t.syncCode(true);
+ return t;
+ }
+ return t.$ta.val();
+ },
+ syncTextarea: function () {
+ var t = this;
+ t.$ta.val(t.$ed.text().trim().length > 0 || t.$ed.find('hr,img,embed,iframe,input').length > 0 ? t.$ed.html() : '');
+ },
+ syncCode: function (force) {
+ var t = this;
+ if (!force && t.$ed.is(':visible')) {
+ t.syncTextarea();
+ } else {
+ // wrap the content in a div it's easier to get the innerhtml
+ var html = $('<div>').html(t.$ta.val());
+ //scrub the html before loading into the doc
+ var safe = $('<div>').append(html);
+ $(t.o.tagsToRemove.join(','), safe).remove();
+ t.$ed.html(safe.contents().html());
+ }
+
+ if (t.o.autogrow) {
+ t.height = t.$ed.height();
+ if (t.height !== t.$ta.css('height')) {
+ t.$ta.css({height: t.height});
+ t.$c.trigger('tbwresize');
+ }
+ }
+ if (t.o.autogrowOnEnter) {
+ // t.autogrowEditorOnEnter();
+ t.$ed.height('auto');
+ var totalheight = t.autogrowOnEnterWasFocused ? t.$ed[0].scrollHeight : t.$ed.css('min-height');
+ if (totalheight !== t.$ta.css('height')) {
+ t.$ed.css({height: totalheight});
+ t.$c.trigger('tbwresize');
+ }
+ }
+ },
+
+ // Analyse and update to semantic code
+ // @param force : force to sync code from textarea
+ // @param full : wrap text nodes in <p>
+ // @param keepRange : leave selection range as it is
+ semanticCode: function (force, full, keepRange) {
+ var t = this;
+ t.saveRange();
+ t.syncCode(force);
+
+ if (t.o.semantic) {
+ t.semanticTag('b', 'strong');
+ t.semanticTag('i', 'em');
+ t.semanticTag('s', 'del');
+ t.semanticTag('strike', 'del');
+
+ if (full) {
+ var inlineElementsSelector = t.o.inlineElementsSelector,
+ blockElementsSelector = ':not(' + inlineElementsSelector + ')';
+
+ // Wrap text nodes in span for easier processing
+ t.$ed.contents().filter(function () {
+ return this.nodeType === 3 && this.nodeValue.trim().length > 0;
+ }).wrap('<span data-tbw/>');
+
+ // Wrap groups of inline elements in paragraphs (recursive)
+ var wrapInlinesInParagraphsFrom = function ($from) {
+ if ($from.length !== 0) {
+ var $finalParagraph = $from.nextUntil(blockElementsSelector).addBack().wrapAll('<p/>').parent(),
+ $nextElement = $finalParagraph.nextAll(inlineElementsSelector).first();
+ $finalParagraph.next('br').remove();
+ wrapInlinesInParagraphsFrom($nextElement);
+ }
+ };
+ wrapInlinesInParagraphsFrom(t.$ed.children(inlineElementsSelector).first());
+
+ t.semanticTag('div', 'p', true);
+
+ // Unwrap paragraphs content, containing nothing usefull
+ t.$ed.find('p').filter(function () {
+ // Don't remove currently being edited element
+ if (t.range && this === t.range.startContainer) {
+ return false;
+ }
+ return $(this).text().trim().length === 0 && $(this).children().not('br,span').length === 0;
+ }).contents().unwrap();
+
+ // Get rid of temporial span's
+ $('[data-tbw]', t.$ed).contents().unwrap();
+
+ // Remove empty <p>
+ t.$ed.find('p:empty').remove();
+ }
+
+ if (!keepRange) {
+ t.restoreRange();
+ }
+
+ t.syncTextarea();
+ }
+ },
+
+ semanticTag: function (oldTag, newTag, copyAttributes) {
+ $(oldTag, this.$ed).each(function () {
+ var $oldTag = $(this);
+ $oldTag.wrap('<' + newTag + '/>');
+ if (copyAttributes) {
+ $.each($oldTag.prop('attributes'), function () {
+ $oldTag.parent().attr(this.name, this.value);
+ });
+ }
+ $oldTag.contents().unwrap();
+ });
+ },
+
+ // Function call when user click on "Insert Link"
+ createLink: function () {
+ var t = this,
+ documentSelection = t.doc.getSelection(),
+ node = documentSelection.focusNode,
+ url,
+ title,
+ target;
+
+ while (['A', 'DIV'].indexOf(node.nodeName) < 0) {
+ node = node.parentNode;
+ }
+
+ if (node && node.nodeName === 'A') {
+ var $a = $(node);
+ url = $a.attr('href');
+ title = $a.attr('title');
+ target = $a.attr('target');
+ var range = t.doc.createRange();
+ range.selectNode(node);
+ documentSelection.removeAllRanges();
+ documentSelection.addRange(range);
+ }
+
+ t.saveRange();
+
+ t.openModalInsert(t.lang.createLink, {
+ url: {
+ label: 'URL',
+ required: true,
+ value: url
+ },
+ title: {
+ label: t.lang.title,
+ value: title
+ },
+ text: {
+ label: t.lang.text,
+ value: new XMLSerializer().serializeToString(documentSelection.getRangeAt(0).cloneContents())
+ },
+ target: {
+ label: t.lang.target,
+ value: target
+ }
+ }, function (v) { // v is value
+ var link = $(['<a href="', v.url, '">', v.text, '</a>'].join(''));
+ if (v.title.length > 0) {
+ link.attr('title', v.title);
+ }
+ if (v.target.length > 0) {
+ link.attr('target', v.target);
+ }
+ t.range.deleteContents();
+ t.range.insertNode(link[0]);
+ t.syncCode();
+ t.$c.trigger('tbwchange');
+ return true;
+ });
+ },
+ unlink: function () {
+ var t = this,
+ documentSelection = t.doc.getSelection(),
+ node = documentSelection.focusNode;
+
+ if (documentSelection.isCollapsed) {
+ while (['A', 'DIV'].indexOf(node.nodeName) < 0) {
+ node = node.parentNode;
+ }
+
+ if (node && node.nodeName === 'A') {
+ var range = t.doc.createRange();
+ range.selectNode(node);
+ documentSelection.removeAllRanges();
+ documentSelection.addRange(range);
+ }
+ }
+ t.execCmd('unlink', undefined, undefined, true);
+ },
+ insertImage: function () {
+ var t = this;
+ t.saveRange();
+
+ var options = {
+ url: {
+ label: 'URL',
+ required: true
+ },
+ alt: {
+ label: t.lang.description,
+ value: t.getRangeText()
+ }
+ };
+
+ if (t.o.imageWidthModalEdit) {
+ options.width = {};
+ }
+
+ t.openModalInsert(t.lang.insertImage, options, function (v) { // v are values
+ t.execCmd('insertImage', v.url);
+ var $img = $('img[src="' + v.url + '"]:not([alt])', t.$box);
+ $img.attr('alt', v.alt);
+
+ if (t.o.imageWidthModalEdit) {
+ $img.attr({
+ width: v.width
+ });
+ }
+
+ t.syncCode();
+ t.$c.trigger('tbwchange');
+
+ return true;
+ });
+ },
+ fullscreen: function () {
+ var t = this,
+ prefix = t.o.prefix,
+ fullscreenCssClass = prefix + 'fullscreen',
+ isFullscreen;
+
+ t.$box.toggleClass(fullscreenCssClass);
+ isFullscreen = t.$box.hasClass(fullscreenCssClass);
+ $('body').toggleClass(prefix + 'body-fullscreen', isFullscreen);
+ $(window).trigger('scroll');
+ t.$c.trigger('tbw' + (isFullscreen ? 'open' : 'close') + 'fullscreen');
+ },
+
+
+ /*
+ * Call method of trumbowyg if exist
+ * else try to call anonymous function
+ * and finaly native execCommand
+ */
+ execCmd: function (cmd, param, forceCss, skipTrumbowyg) {
+ var t = this;
+ skipTrumbowyg = !!skipTrumbowyg || '';
+
+ if (cmd !== 'dropdown') {
+ t.$ed.focus();
+ }
+
+ try {
+ t.doc.execCommand('styleWithCSS', false, forceCss || false);
+ } catch (c) {
+ }
+
+ try {
+ t[cmd + skipTrumbowyg](param);
+ } catch (c) {
+ try {
+ cmd(param);
+ } catch (e2) {
+ if (cmd === 'insertHorizontalRule') {
+ param = undefined;
+ } else if (cmd === 'formatBlock' && t.isIE) {
+ param = '<' + param + '>';
+ }
+
+ t.doc.execCommand(cmd, false, param);
+
+ t.syncCode();
+ t.semanticCode(false, true);
+ }
+
+ if (cmd !== 'dropdown') {
+ t.updateButtonPaneStatus();
+ t.$c.trigger('tbwchange');
+ }
+ }
+ },
+
+
+ // Open a modal box
+ openModal: function (title, content) {
+ var t = this,
+ prefix = t.o.prefix;
+
+ // No open a modal box when exist other modal box
+ if ($('.' + prefix + 'modal-box', t.$box).length > 0) {
+ return false;
+ }
+ if (t.o.autogrowOnEnter) {
+ t.autogrowOnEnterDontClose = true;
+ }
+
+ t.saveRange();
+ t.showOverlay();
+
+ // Disable all btnPane btns
+ t.$btnPane.addClass(prefix + 'disable');
+
+ // Build out of ModalBox, it's the mask for animations
+ var $modal = $('<div/>', {
+ class: prefix + 'modal ' + prefix + 'fixed-top'
+ }).css({
+ top: t.$btnPane.height()
+ }).appendTo(t.$box);
+
+ // Click on overlay close modal by cancelling them
+ t.$overlay.one('click', function () {
+ $modal.trigger(CANCEL_EVENT);
+ return false;
+ });
+
+ // Build the form
+ var $form = $('<form/>', {
+ action: '',
+ html: content
+ })
+ .on('submit', function () {
+ $modal.trigger(CONFIRM_EVENT);
+ return false;
+ })
+ .on('reset', function () {
+ $modal.trigger(CANCEL_EVENT);
+ return false;
+ })
+ .on('submit reset', function () {
+ if (t.o.autogrowOnEnter) {
+ t.autogrowOnEnterDontClose = false;
+ }
+ });
+
+
+ // Build ModalBox and animate to show them
+ var $box = $('<div/>', {
+ class: prefix + 'modal-box',
+ html: $form
+ })
+ .css({
+ top: '-' + t.$btnPane.outerHeight() + 'px',
+ opacity: 0
+ })
+ .appendTo($modal)
+ .animate({
+ top: 0,
+ opacity: 1
+ }, 100);
+
+
+ // Append title
+ $('<span/>', {
+ text: title,
+ class: prefix + 'modal-title'
+ }).prependTo($box);
+
+ $modal.height($box.outerHeight() + 10);
+
+
+ // Focus in modal box
+ $('input:first', $box).focus();
+
+
+ // Append Confirm and Cancel buttons
+ t.buildModalBtn('submit', $box);
+ t.buildModalBtn('reset', $box);
+
+
+ $(window).trigger('scroll');
+
+ return $modal;
+ },
+ // @param n is name of modal
+ buildModalBtn: function (n, $modal) {
+ var t = this,
+ prefix = t.o.prefix;
+
+ return $('<button/>', {
+ class: prefix + 'modal-button ' + prefix + 'modal-' + n,
+ type: n,
+ text: t.lang[n] || n
+ }).appendTo($('form', $modal));
+ },
+ // close current modal box
+ closeModal: function () {
+ var t = this,
+ prefix = t.o.prefix;
+
+ t.$btnPane.removeClass(prefix + 'disable');
+ t.$overlay.off();
+
+ // Find the modal box
+ var $modalBox = $('.' + prefix + 'modal-box', t.$box);
+
+ $modalBox.animate({
+ top: '-' + $modalBox.height()
+ }, 100, function () {
+ $modalBox.parent().remove();
+ t.hideOverlay();
+ });
+
+ t.restoreRange();
+ },
+ // Preformated build and management modal
+ openModalInsert: function (title, fields, cmd) {
+ var t = this,
+ prefix = t.o.prefix,
+ lg = t.lang,
+ html = '';
+
+ $.each(fields, function (fieldName, field) {
+ var l = field.label,
+ n = field.name || fieldName,
+ a = field.attributes || {};
+
+ var attr = Object.keys(a).map(function (prop) {
+ return prop + '="' + a[prop] + '"';
+ }).join(' ');
+
+ html += '<label><input type="' + (field.type || 'text') + '" name="' + n + '" value="' + (field.value || '').replace(/"/g, '&quot;') + '"' + attr + '><span class="' + prefix + 'input-infos"><span>' +
+ ((!l) ? (lg[fieldName] ? lg[fieldName] : fieldName) : (lg[l] ? lg[l] : l)) +
+ '</span></span></label>';
+ });
+
+ return t.openModal(title, html)
+ .on(CONFIRM_EVENT, function () {
+ var $form = $('form', $(this)),
+ valid = true,
+ values = {};
+
+ $.each(fields, function (fieldName, field) {
+ var $field = $('input[name="' + fieldName + '"]', $form),
+ inputType = $field.attr('type');
+
+ if (inputType.toLowerCase() === 'checkbox') {
+ values[fieldName] = $field.is(':checked');
+ } else {
+ values[fieldName] = $.trim($field.val());
+ }
+ // Validate value
+ if (field.required && values[fieldName] === '') {
+ valid = false;
+ t.addErrorOnModalField($field, t.lang.required);
+ } else if (field.pattern && !field.pattern.test(values[fieldName])) {
+ valid = false;
+ t.addErrorOnModalField($field, field.patternError);
+ }
+ });
+
+ if (valid) {
+ t.restoreRange();
+
+ if (cmd(values, fields)) {
+ t.syncCode();
+ t.$c.trigger('tbwchange');
+ t.closeModal();
+ $(this).off(CONFIRM_EVENT);
+ }
+ }
+ })
+ .one(CANCEL_EVENT, function () {
+ $(this).off(CONFIRM_EVENT);
+ t.closeModal();
+ });
+ },
+ addErrorOnModalField: function ($field, err) {
+ var prefix = this.o.prefix,
+ $label = $field.parent();
+
+ $field
+ .on('change keyup', function () {
+ $label.removeClass(prefix + 'input-error');
+ });
+
+ $label
+ .addClass(prefix + 'input-error')
+ .find('input+span')
+ .append(
+ $('<span/>', {
+ class: prefix + 'msg-error',
+ text: err
+ })
+ );
+ },
+
+ getDefaultImgDblClickHandler: function () {
+ var t = this;
+
+ return function () {
+ var $img = $(this),
+ src = $img.attr('src'),
+ base64 = '(Base64)';
+
+ if (src.indexOf('data:image') === 0) {
+ src = base64;
+ }
+
+ var options = {
+ url: {
+ label: 'URL',
+ value: src,
+ required: true
+ },
+ alt: {
+ label: t.lang.description,
+ value: $img.attr('alt')
+ }
+ };
+
+ if (t.o.imageWidthModalEdit) {
+ options.width = {
+ value: $img.attr('width') ? $img.attr('width') : ''
+ };
+ }
+
+ t.openModalInsert(t.lang.insertImage, options, function (v) {
+ if (v.src !== base64) {
+ $img.attr({
+ src: v.url
+ });
+ }
+ $img.attr({
+ alt: v.alt
+ });
+
+ if (t.o.imageWidthModalEdit) {
+ if (parseInt(v.width) > 0) {
+ $img.attr({
+ width: v.width
+ });
+ } else {
+ $img.removeAttr('width');
+ }
+ }
+
+ return true;
+ });
+ return false;
+ };
+ },
+
+ // Range management
+ saveRange: function () {
+ var t = this,
+ documentSelection = t.doc.getSelection();
+
+ t.range = null;
+
+ if (documentSelection.rangeCount) {
+ var savedRange = t.range = documentSelection.getRangeAt(0),
+ range = t.doc.createRange(),
+ rangeStart;
+ range.selectNodeContents(t.$ed[0]);
+ range.setEnd(savedRange.startContainer, savedRange.startOffset);
+ rangeStart = (range + '').length;
+ t.metaRange = {
+ start: rangeStart,
+ end: rangeStart + (savedRange + '').length
+ };
+ }
+ },
+ restoreRange: function () {
+ var t = this,
+ metaRange = t.metaRange,
+ savedRange = t.range,
+ documentSelection = t.doc.getSelection(),
+ range;
+
+ if (!savedRange) {
+ return;
+ }
+
+ if (metaRange && metaRange.start !== metaRange.end) { // Algorithm from http://jsfiddle.net/WeWy7/3/
+ var charIndex = 0,
+ nodeStack = [t.$ed[0]],
+ node,
+ foundStart = false,
+ stop = false;
+
+ range = t.doc.createRange();
+
+ while (!stop && (node = nodeStack.pop())) {
+ if (node.nodeType === 3) {
+ var nextCharIndex = charIndex + node.length;
+ if (!foundStart && metaRange.start >= charIndex && metaRange.start <= nextCharIndex) {
+ range.setStart(node, metaRange.start - charIndex);
+ foundStart = true;
+ }
+ if (foundStart && metaRange.end >= charIndex && metaRange.end <= nextCharIndex) {
+ range.setEnd(node, metaRange.end - charIndex);
+ stop = true;
+ }
+ charIndex = nextCharIndex;
+ } else {
+ var cn = node.childNodes,
+ i = cn.length;
+
+ while (i > 0) {
+ i -= 1;
+ nodeStack.push(cn[i]);
+ }
+ }
+ }
+ }
+
+ documentSelection.removeAllRanges();
+ documentSelection.addRange(range || savedRange);
+ },
+ getRangeText: function () {
+ return this.range + '';
+ },
+
+ updateButtonPaneStatus: function () {
+ var t = this,
+ prefix = t.o.prefix,
+ tags = t.getTagsRecursive(t.doc.getSelection().focusNode),
+ activeClasses = prefix + 'active-button ' + prefix + 'active';
+
+ $('.' + prefix + 'active-button', t.$btnPane).removeClass(activeClasses);
+ $.each(tags, function (i, tag) {
+ var btnName = t.tagToButton[tag.toLowerCase()],
+ $btn = $('.' + prefix + btnName + '-button', t.$btnPane);
+
+ if ($btn.length > 0) {
+ $btn.addClass(activeClasses);
+ } else {
+ try {
+ $btn = $('.' + prefix + 'dropdown .' + prefix + btnName + '-dropdown-button', t.$box);
+ var dropdownBtnName = $btn.parent().data('dropdown');
+ $('.' + prefix + dropdownBtnName + '-button', t.$box).addClass(activeClasses);
+ } catch (e) {
+ }
+ }
+ });
+ },
+ getTagsRecursive: function (element, tags) {
+ var t = this;
+ tags = tags || (element && element.tagName ? [element.tagName] : []);
+
+ if (element && element.parentNode) {
+ element = element.parentNode;
+ } else {
+ return tags;
+ }
+
+ var tag = element.tagName;
+ if (tag === 'DIV') {
+ return tags;
+ }
+ if (tag === 'P' && element.style.textAlign !== '') {
+ tags.push(element.style.textAlign);
+ }
+
+ $.each(t.tagHandlers, function (i, tagHandler) {
+ tags = tags.concat(tagHandler(element, t));
+ });
+
+ tags.push(tag);
+
+ return t.getTagsRecursive(element, tags).filter(function(tag) { return tag != null; });
+ },
+
+ // Plugins
+ initPlugins: function () {
+ var t = this;
+ t.loadedPlugins = [];
+ $.each($.trumbowyg.plugins, function (name, plugin) {
+ if (!plugin.shouldInit || plugin.shouldInit(t)) {
+ plugin.init(t);
+ if (plugin.tagHandler) {
+ t.tagHandlers.push(plugin.tagHandler);
+ }
+ t.loadedPlugins.push(plugin);
+ }
+ });
+ },
+ destroyPlugins: function () {
+ $.each(this.loadedPlugins, function (i, plugin) {
+ if (plugin.destroy) {
+ plugin.destroy();
+ }
+ });
+ }
+ };
+ })(navigator, window, document, jQuery);
public/stylesheets/app.scss +3 -1
@@ @@ -49,10 +49,12 @@
@include foundation-visibility-classes;
@include foundation-float-classes;
- @import 'footer';
+ @import "vendor/trumbowyg";
+ @import "footer";
@import "services";
@import "header";
+
body, html {
height: 100%;
background: $white;
public/stylesheets/vendor/trumbowyg.scss +794 -0
@@ @@ -0,0 +1,794 @@
+ /**
+ * Trumbowyg v2.9.4 - A lightweight WYSIWYG editor
+ * Default stylesheet for Trumbowyg editor
+ * ------------------------
+ * @link http://alex-d.github.io/Trumbowyg
+ * @license MIT
+ * @author Alexandre Demode (Alex-D)
+ * Twitter : @AlexandreDemode
+ * Website : alex-d.fr
+ */
+
+ $light-color: #ecf0f1 !default;
+ $dark-color: #222 !default;
+
+ $modal-submit-color: #2ecc71 !default;
+ $modal-reset-color: #EEE !default;
+
+ $transition-duration: 150ms !default;
+ $slow-transition-duration: 300ms !default;
+
+ #trumbowyg-icons {
+ overflow: hidden;
+ visibility: hidden;
+ height: 0;
+ width: 0;
+
+ svg {
+ height: 0;
+ width: 0;
+ }
+ }
+
+ .trumbowyg-box {
+ *,
+ *::before,
+ *::after {
+ box-sizing: border-box;
+ }
+
+ svg {
+ width: 17px;
+ height: 100%;
+ fill: $dark-color;
+ }
+ }
+
+ .trumbowyg-box,
+ .trumbowyg-editor {
+ display: block;
+ position: relative;
+ border: 1px solid #DDD;
+ width: 100%;
+ min-height: 300px;
+ margin: 17px auto;
+ }
+
+ .trumbowyg-box .trumbowyg-editor {
+ margin: 0 auto;
+ }
+
+ .trumbowyg-box.trumbowyg-fullscreen {
+ background: #FEFEFE;
+ border: none !important;
+ }
+
+ .trumbowyg-editor,
+ .trumbowyg-textarea {
+ position: relative;
+ box-sizing: border-box;
+ padding: 20px;
+ min-height: 300px;
+ width: 100%;
+ border-style: none;
+ resize: none;
+ outline: none;
+ overflow: auto;
+
+ &.trumbowyg-autogrow-on-enter {
+ transition: height $slow-transition-duration ease-out;
+ }
+ }
+
+ .trumbowyg-box-blur .trumbowyg-editor {
+ *,
+ &::before {
+ color: transparent !important;
+ text-shadow: 0 0 7px #333;
+
+ @media screen and (min-width: 0 \0) {
+ color: rgba(200, 200, 200, 0.6) !important;
+ }
+ @supports (-ms-accelerator:true) {
+ color: rgba(200, 200, 200, 0.6) !important;
+ }
+ }
+ img,
+ hr {
+ opacity: 0.2;
+ }
+ }
+
+ .trumbowyg-textarea {
+ position: relative;
+ display: block;
+ overflow: auto;
+ border: none;
+ font-size: 14px;
+ font-family: "Inconsolata", "Consolas", "Courier", "Courier New", sans-serif;
+ line-height: 18px;
+ }
+
+ .trumbowyg-box.trumbowyg-editor-visible {
+ .trumbowyg-textarea {
+ height: 1px !important;
+ width: 25%;
+ min-height: 0 !important;
+ padding: 0 !important;
+ background: none;
+ opacity: 0 !important;
+ }
+ }
+
+ .trumbowyg-box.trumbowyg-editor-hidden {
+ .trumbowyg-textarea {
+ display: block;
+ }
+ .trumbowyg-editor {
+ display: none;
+ }
+ }
+
+ .trumbowyg-box.trumbowyg-disabled {
+ .trumbowyg-textarea {
+ opacity: 0.8;
+ background: none;
+ }
+ }
+
+ .trumbowyg-editor[contenteditable=true]:empty:not(:focus)::before {
+ content: attr(placeholder);
+ color: #999;
+ pointer-events: none;
+ }
+
+ .trumbowyg-button-pane {
+ width: 100%;
+ min-height: 36px;
+ background: $light-color;
+ border-bottom: 1px solid darken($light-color, 7%);
+ margin: 0;
+ padding: 0 5px;
+ position: relative;
+ list-style-type: none;
+ line-height: 10px;
+ backface-visibility: hidden;
+ z-index: 11;
+
+ &::after {
+ content: " ";
+ display: block;
+ position: absolute;
+ top: 36px;
+ left: 0;
+ right: 0;
+ width: 100%;
+ height: 1px;
+ background: darken($light-color, 7%);
+ }
+
+ .trumbowyg-button-group {
+ display: inline-block;
+
+ .trumbowyg-fullscreen-button svg {
+ color: transparent;
+ }
+
+ & + .trumbowyg-button-group::before {
+ content: " ";
+ display: inline-block;
+ width: 1px;
+ background: darken($light-color, 7%);
+ margin: 0 5px;
+ height: 35px;
+ vertical-align: top;
+ }
+ }
+
+ button {
+ display: inline-block;
+ position: relative;
+ width: 35px;
+ height: 35px;
+ padding: 1px 6px !important;
+ margin-bottom: 1px;
+ overflow: hidden;
+ border: none;
+ cursor: pointer;
+ background: none;
+ vertical-align: middle;
+ transition: background-color $transition-duration, opacity $transition-duration;
+
+ &.trumbowyg-textual-button {
+ width: auto;
+ line-height: 35px;
+ user-select: none;
+ }
+ }
+
+ &.trumbowyg-disable button:not(.trumbowyg-not-disable):not(.trumbowyg-active),
+ .trumbowyg-disabled & button:not(.trumbowyg-not-disable):not(.trumbowyg-viewHTML-button) {
+ opacity: 0.2;
+ cursor: default;
+ }
+ &.trumbowyg-disable,
+ .trumbowyg-disabled & {
+ .trumbowyg-button-group::before {
+ background: darken($light-color, 3%);
+ }
+ }
+
+ button:not(.trumbowyg-disable):hover,
+ button:not(.trumbowyg-disable):focus,
+ button.trumbowyg-active {
+ background-color: #FFF;
+ outline: none;
+ }
+
+ .trumbowyg-open-dropdown {
+ &::after {
+ display: block;
+ content: " ";
+ position: absolute;
+ top: 25px;
+ right: 3px;
+ height: 0;
+ width: 0;
+ border: 3px solid transparent;
+ border-top-color: #555;
+ }
+
+ &.trumbowyg-textual-button {
+ padding-left: 10px !important;
+ padding-right: 18px !important;
+
+ &::after {
+ top: 17px;
+ right: 7px;
+ }
+ }
+ }
+
+ .trumbowyg-right {
+ float: right;
+
+ &::before {
+ display: none !important;
+ }
+ }
+ }
+
+ .trumbowyg-dropdown {
+ width: 200px;
+ border: 1px solid $light-color;
+ padding: 5px 0;
+ border-top: none;
+ background: #FFF;
+ margin-left: -1px;
+ box-shadow: rgba(0, 0, 0, .1) 0 2px 3px;
+ z-index: 12;
+
+ button {
+ display: block;
+ width: 100%;
+ height: 35px;
+ line-height: 35px;
+ text-decoration: none;
+ background: #FFF;
+ padding: 0 10px;
+ color: #333 !important;
+ border: none;
+ cursor: pointer;
+ text-align: left;
+ font-size: 15px;
+ transition: all $transition-duration;
+
+ &:hover,
+ &:focus {
+ background: $light-color;
+ }
+
+ svg {
+ float: left;
+ margin-right: 14px;
+ }
+ }
+ }
+
+ /* Modal box */
+ .trumbowyg-modal {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ max-width: 520px;
+ width: 100%;
+ height: 350px;
+ z-index: 12;
+ overflow: hidden;
+ backface-visibility: hidden;
+ }
+
+ .trumbowyg-modal-box {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ max-width: 500px;
+ width: calc(100% - 20px);
+ padding-bottom: 45px;
+ z-index: 1;
+ background-color: #FFF;
+ text-align: center;
+ font-size: 14px;
+ box-shadow: rgba(0, 0, 0, .2) 0 2px 3px;
+ backface-visibility: hidden;
+
+ .trumbowyg-modal-title {
+ font-size: 24px;
+ font-weight: bold;
+ margin: 0 0 20px;
+ padding: 15px 0 13px;
+ display: block;
+ border-bottom: 1px solid #EEE;
+ color: #333;
+ background: lighten($light-color, 5%);
+ }
+
+ .trumbowyg-progress {
+ width: 100%;
+ height: 3px;
+ position: absolute;
+ top: 58px;
+
+ .trumbowyg-progress-bar {
+ background: #2BC06A;
+ width: 0;
+ height: 100%;
+ transition: width $transition-duration linear;
+ }
+ }
+
+ label {
+ display: block;
+ position: relative;
+ margin: 15px 12px;
+ height: 29px;
+ line-height: 29px;
+ overflow: hidden;
+
+ .trumbowyg-input-infos {
+ display: block;
+ text-align: left;
+ height: 25px;
+ line-height: 25px;
+ transition: all 150ms;
+
+ span {
+ display: block;
+ color: darken($light-color, 45%);
+ background-color: lighten($light-color, 5%);
+ border: 1px solid #DEDEDE;
+ padding: 0 7px;
+ width: 150px;
+ }
+ span.trumbowyg-msg-error {
+ color: #e74c3c;
+ }
+ }
+
+ &.trumbowyg-input-error {
+ input,
+ textarea {
+ border: 1px solid #e74c3c;
+ }
+
+ .trumbowyg-input-infos {
+ margin-top: -27px;
+ }
+ }
+
+ input {
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 27px;
+ line-height: 27px;
+ border: 1px solid #DEDEDE;
+ background: #fff;
+ font-size: 14px;
+ max-width: 330px;
+ width: 70%;
+ padding: 0 7px;
+ transition: all $transition-duration;
+
+ &:hover,
+ &:focus {
+ outline: none;
+ border: 1px solid #95a5a6;
+ }
+ &:focus {
+ background: lighten($light-color, 5%);
+ }
+ }
+ }
+
+ .error {
+ margin-top: 25px;
+ display: block;
+ color: red;
+ }
+
+ .trumbowyg-modal-button {
+ position: absolute;
+ bottom: 10px;
+ right: 0;
+ text-decoration: none;
+ color: #FFF;
+ display: block;
+ width: 100px;
+ height: 35px;
+ line-height: 33px;
+ margin: 0 10px;
+ background-color: #333;
+ border: none;
+ cursor: pointer;
+ font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif;
+ font-size: 16px;
+ transition: all $transition-duration;
+
+ &.trumbowyg-modal-submit {
+ right: 110px;
+ background: darken($modal-submit-color, 3%);
+
+ &:hover,
+ &:focus {
+ background: lighten($modal-submit-color, 5%);
+ outline: none;
+ }
+ &:active {
+ background: darken($modal-submit-color, 10%);
+ }
+ }
+
+ &.trumbowyg-modal-reset {
+ color: #555;
+ background: darken($modal-reset-color, 3%);
+
+ &:hover,
+ &:focus {
+ background: lighten($modal-reset-color, 5%);
+ outline: none;
+ }
+ &:active {
+ background: darken($modal-reset-color, 10%);
+ }
+ }
+ }
+ }
+
+ .trumbowyg-overlay {
+ position: absolute;
+ background-color: rgba(255, 255, 255, 0.5);
+ height: 100%;
+ width: 100%;
+ left: 0;
+ display: none;
+ top: 0;
+ z-index: 10;
+ }
+
+ /**
+ * Fullscreen
+ */
+ body.trumbowyg-body-fullscreen {
+ overflow: hidden;
+ }
+
+ .trumbowyg-fullscreen {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ z-index: 99999;
+
+ &.trumbowyg-box,
+ .trumbowyg-editor {
+ border: none;
+ }
+ .trumbowyg-editor,
+ .trumbowyg-textarea {
+ height: calc(100% - 37px) !important;
+ overflow: auto;
+ }
+ .trumbowyg-overlay {
+ height: 100% !important;
+ }
+ .trumbowyg-button-group .trumbowyg-fullscreen-button svg {
+ color: $dark-color;
+ fill: transparent;
+ }
+ }
+
+ .trumbowyg-editor {
+ object,
+ embed,
+ video,
+ img {
+ max-width: 100%;
+ }
+ video,
+ img {
+ height: auto;
+ }
+ img {
+ cursor: move;
+ }
+
+ /*
+ * lset for resetCss option
+ */
+ &.trumbowyg-reset-css {
+ background: #FEFEFE !important;
+ font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif !important;
+ font-size: 14px !important;
+ line-height: 1.45em !important;
+ color: #333;
+
+ a {
+ color: #15c !important;
+ text-decoration: underline !important;
+ }
+
+ div,
+ p,
+ ul,
+ ol,
+ blockquote {
+ box-shadow: none !important;
+ background: none !important;
+ margin: 0 !important;
+ margin-bottom: 15px !important;
+ line-height: 1.4em !important;
+ font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif !important;
+ font-size: 14px !important;
+ border: none;
+ }
+ iframe,
+ object,
+ hr {
+ margin-bottom: 15px !important;
+ }
+ blockquote {
+ margin-left: 32px !important;
+ font-style: italic !important;
+ color: #555;
+ }
+ ul,
+ ol {
+ padding-left: 20px !important;
+ }
+ ul ul,
+ ol ol,
+ ul ol,
+ ol ul {
+ border: none;
+ margin: 2px !important;
+ padding: 0 !important;
+ padding-left: 24px !important;
+ }
+ hr {
+ display: block;
+ height: 1px;
+ border: none;
+ border-top: 1px solid #CCC;
+ }
+
+ h1,
+ h2,
+ h3,
+ h4 {
+ color: #111;
+ background: none;
+ margin: 0 !important;
+ padding: 0 !important;
+ font-weight: bold;
+ }
+
+ h1 {
+ font-size: 32px !important;
+ line-height: 38px !important;
+ margin-bottom: 20px !important;
+ }
+ h2 {
+ font-size: 26px !important;
+ line-height: 34px !important;
+ margin-bottom: 15px !important;
+ }
+ h3 {
+ font-size: 22px !important;
+ line-height: 28px !important;
+ margin-bottom: 7px !important;
+ }
+ h4 {
+ font-size: 16px !important;
+ line-height: 22px !important;
+ margin-bottom: 7px !important;
+ }
+ }
+ }
+
+ /*
+ * Dark theme
+ */
+ .trumbowyg-dark {
+ .trumbowyg-textarea {
+ background: #111;
+ color: #ddd;
+ }
+ .trumbowyg-box {
+ border: 1px solid lighten($dark-color, 7%);
+
+ &.trumbowyg-fullscreen {
+ background: #111;
+ }
+ &.trumbowyg-box-blur .trumbowyg-editor {
+ *,
+ &::before {
+ text-shadow: 0 0 7px #ccc;
+
+ @media screen and (min-width: 0 \0
+ ) {
+ color: rgba(20, 20, 20, 0.6) !important;
+ }
+ @supports (-ms-accelerator:true) {
+ color: rgba(20, 20, 20, 0.6) !important;
+ }
+ }
+ }
+
+ svg {
+ fill: $light-color;
+ color: $light-color;
+ }
+ }
+ .trumbowyg-button-pane {
+ background-color: $dark-color;
+ border-bottom-color: lighten($dark-color, 7%);
+
+ &::after {
+ background: lighten($dark-color, 7%);
+ }
+
+ .trumbowyg-button-group:not(:empty) {
+ &::before {
+ background-color: lighten($dark-color, 7%);
+ }
+ .trumbowyg-fullscreen-button svg {
+ color: transparent;
+ }
+ }
+
+ &.trumbowyg-disable {
+ .trumbowyg-button-group::before {
+ background-color: lighten($dark-color, 3%);
+ }
+ }
+
+ button:not(.trumbowyg-disable):hover,
+ button:not(.trumbowyg-disable):focus,
+ button.trumbowyg-active {
+ background-color: #333;
+ }
+
+ .trumbowyg-open-dropdown::after {
+ border-top-color: #fff;
+ }
+ }
+ .trumbowyg-fullscreen {
+ .trumbowyg-button-group .trumbowyg-fullscreen-button svg {
+ color: $light-color;
+ fill: transparent;
+ }
+ }
+
+ .trumbowyg-dropdown {
+ border-color: $dark-color;
+ background: #333;
+ box-shadow: rgba(0, 0, 0, .3) 0 2px 3px;
+
+ button {
+ background: #333;
+ color: #fff !important;
+
+ &:hover,
+ &:focus {
+ background: $dark-color;
+ }
+ }
+ }
+
+ // Modal box
+ .trumbowyg-modal-box {
+ background-color: $dark-color;
+
+ .trumbowyg-modal-title {
+ border-bottom: 1px solid #555;
+ color: #fff;
+ background: lighten($dark-color, 10%);
+ }
+
+ label {
+ display: block;
+ position: relative;
+ margin: 15px 12px;
+ height: 27px;
+ line-height: 27px;
+ overflow: hidden;
+
+ .trumbowyg-input-infos {
+ span {
+ color: #eee;
+ background-color: lighten($dark-color, 5%);
+ border-color: $dark-color;
+ }
+ span.trumbowyg-msg-error {
+ color: #e74c3c;
+ }
+ }
+
+ &.trumbowyg-input-error {
+ input,
+ textarea {
+ border-color: #e74c3c;
+ }
+ }
+
+ input {
+ border-color: $dark-color;
+ color: #eee;
+ background: #333;
+
+ &:hover,
+ &:focus {
+ border-color: lighten($dark-color, 25%);
+ }
+ &:focus {
+ background-color: lighten($dark-color, 5%);
+ }
+ }
+ }
+
+ .trumbowyg-modal-button {
+ &.trumbowyg-modal-submit {
+ background: darken($modal-submit-color, 20%);
+
+ &:hover,
+ &:focus {
+ background: darken($modal-submit-color, 10%);
+ }
+ &:active {
+ background: darken($modal-submit-color, 25%);
+ }
+ }
+ &.trumbowyg-modal-reset {
+ background: #333;
+ color: #ccc;
+
+ &:hover,
+ &:focus {
+ background: #444;
+ }
+ &:active {
+ background: #111;
+ }
+ }
+ }
+ }
+ .trumbowyg-overlay {
+ background-color: rgba(15, 15, 15, 0.6);
+ }
+ }