diff --git a/app/assets/javascripts/alchemy/admin.js b/app/assets/javascripts/alchemy/admin.js index 569b200b76..c54c6bc959 100644 --- a/app/assets/javascripts/alchemy/admin.js +++ b/app/assets/javascripts/alchemy/admin.js @@ -5,7 +5,6 @@ //= require jquery-ui/effects/effect-fade //= require jquery-ui/widgets/draggable //= require jquery-ui/widgets/sortable -//= require jquery-ui/widgets/tabs //= require tinymce/tinymce.min //= require_tree ../../../../vendor/assets/javascripts/jquery_plugins/ //= require clipboard.min diff --git a/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee b/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee index 49f9ed79aa..f89782ff4f 100644 --- a/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +++ b/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee @@ -104,7 +104,6 @@ class window.Alchemy.Dialog # Initializes the Dialog body init: -> Alchemy.GUI.init(@dialog_body) - $('#overlay_tabs', @dialog_body).tabs() @watch_remote_forms() # Watches ajax requests inside of dialog body and replaces the content accordingly diff --git a/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee b/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee index f722cc632f..b8874d8c8f 100644 --- a/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +++ b/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee @@ -80,10 +80,11 @@ Alchemy.ElementEditors = # Selects tab for given element selectTabForElement: ($element) -> - $tabs = $("#fixed-elements .sortable-elements") - if $tabs.size() > 0 - $tab = $element.closest(".sortable-elements") - $("#fixed-elements").tabs("option", "active", $tabs.index($tab)) + tabs = document.querySelector("#fixed-elements") + if tabs + panel = $element.closest("sl-tab-panel").attr("name") + tabs.show(panel) + return # Marks an element as selected in the element window and scrolls to it. # diff --git a/app/assets/javascripts/alchemy/alchemy.fixed_elements.js b/app/assets/javascripts/alchemy/alchemy.fixed_elements.js index c51631eb8b..56b7e19e22 100644 --- a/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +++ b/app/assets/javascripts/alchemy/alchemy.fixed_elements.js @@ -1,38 +1,45 @@ -window.Alchemy = Alchemy || {}; +window.Alchemy = Alchemy || {} Alchemy.FixedElements = { - WRAPPER: '
', - TABS: '', + WRAPPER: '', + TABS: '{{label}}', // Builds fixed elements tabs - buildTabs: function(label) { + buildTabs: function (label) { var $wrapper = $(this.WRAPPER), - $tabs = $(this.TABS.replace(/{{label}}/, label)); + $tabs = $(this.TABS.replace(/{{label}}/, label)) - $('#main-content-elements').wrap($wrapper); - $('#fixed-elements').prepend($tabs).tabs().tabs('paging', { - follow: true, - followOnSelect: true - }); + $("#main-content-elements").wrap($wrapper) + $("#fixed-elements").prepend($tabs) }, // Creates a fixed element tab. - createTab: function(element_id, label) { - var $fixed_elements = $('#fixed-elements'), - $tab; - - $('> ul', $fixed_elements).append('
  • ' + label + '
  • '); - $tab = $('
    '); - $fixed_elements.append($tab); - $fixed_elements.tabs().tabs('refresh'); - $fixed_elements.tabs('option', 'active', $('#fixed-elements > div').index($tab)); + createTab: function (element_id, label) { + var $fixed_elements = $("#fixed-elements") + var panel_name = "fixed-element-" + element_id + + var $tab = + '' + label + "" + $fixed_elements.append($tab) + + var $panel = $( + '' + ) + $fixed_elements.append($panel) + window.requestAnimationFrame(function () { + $fixed_elements.get(0).show(panel_name) + }) }, - removeTab: function(element_id) { - var $fixed_elements = $('#fixed-elements'); + removeTab: function (element_id) { + var $fixed_elements = $("#fixed-elements") - $fixed_elements.find('a[href="#fixed-element-' + element_id + '"]').parent().remove(); - $fixed_elements.find('div#fixed-element-' + element_id).remove(); - $fixed_elements.tabs().tabs('refresh'); + $fixed_elements + .find('sl-tab[panel="fixed-element-' + element_id + '"]') + .remove() + $fixed_elements + .find('sl-tab-panel[name="fixed-element-' + element_id + '"]') + .remove() + $fixed_elements.get(0).show("main-content-elements") } -}; +} diff --git a/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee b/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee index d535c86b3a..ea02fbe3f3 100644 --- a/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +++ b/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee @@ -183,27 +183,27 @@ class window.Alchemy.LinkDialog extends Alchemy.Dialog # Checking of what kind the link is (internal, external or file). if @$link.hasClass('external') # Handles an external link. - tab = $('#overlay_tab_external_link') + tab = 'overlay_tab_external_link' @$external_link.val(@$link.attr('href')) else if @$link.hasClass('file') # Handles a file link. - tab = $('#overlay_tab_file_link') + tab = 'overlay_tab_file_link' @$file_link.select2('val', @$link[0].pathname + @$link[0].search) else if @$link.attr('href').match(/^#/) # Handles an anchor link. - tab = $('#overlay_tab_anchor_link') + tab = 'overlay_tab_anchor_link' @$anchor_link.select2('val', @$link.attr('href')) else if @$link.hasClass('internal') # Handles an internal link. - tab = $('#overlay_tab_internal_link') + tab = 'overlay_tab_internal_link' @initInternalLinkTab() else # Emit an event to allow extensions hook into the link overlay. @$overlay_tabs.trigger 'SelectLinkTab.Alchemy', link: @$link if tab - # activate the tab jquery ui 1.10 style o.O - @$overlay_tabs.tabs('option', 'active', $('#overlay_tabs > div').index(tab)) + window.requestAnimationFrame => + @$overlay_tabs.get(0).show(tab) return # Handles actions for internal link tab. diff --git a/app/assets/stylesheets/alchemy/admin.scss b/app/assets/stylesheets/alchemy/admin.scss index 786d60e338..6538a4c136 100644 --- a/app/assets/stylesheets/alchemy/admin.scss +++ b/app/assets/stylesheets/alchemy/admin.scss @@ -39,6 +39,7 @@ @import "alchemy/resource_info"; @import "alchemy/search"; @import "alchemy/selects"; +@import "alchemy/shoelace"; @import "alchemy/sitemap"; @import "alchemy/spinner"; @import "alchemy/tables"; diff --git a/app/assets/stylesheets/alchemy/dialogs.scss b/app/assets/stylesheets/alchemy/dialogs.scss index 0d29bfa930..cdc5adf995 100644 --- a/app/assets/stylesheets/alchemy/dialogs.scss +++ b/app/assets/stylesheets/alchemy/dialogs.scss @@ -201,13 +201,5 @@ $dialog-transition-duration: 150ms; } #overlay_tabs { - margin: -4*$default-padding; - - .ui-tabs-panel { - padding: 4*$default-padding; - } - - .ui-tabs.ui-corner-all { - border-radius: 0; - } + margin: -4 * $default-padding; } diff --git a/app/assets/stylesheets/alchemy/elements.scss b/app/assets/stylesheets/alchemy/elements.scss index 71e792cf2f..61a7cf2dba 100644 --- a/app/assets/stylesheets/alchemy/elements.scss +++ b/app/assets/stylesheets/alchemy/elements.scss @@ -190,13 +190,15 @@ } &.selected:not(.is-fixed), - &:hover { + &:hover:not(.is-fixed) { &:not(.hidden) { box-shadow: 0 2px 8px rgba(#9b9b9b, 0.75); } } - &.selected:not(.is-fixed):not(.folded):not(.dirty):not(.hidden):not(.deprecated) { + &.selected:not(.is-fixed):not(.folded):not(.dirty):not(.hidden):not( + .deprecated + ) { > .element-header { background-color: $element-header-active-bg-color; color: $element-header-active-color; @@ -963,8 +965,10 @@ textarea.has_tinymce { position: relative; } - .element-header { - background-color: transparent; + .element-editor:not(.is-fixed) & { + .element-header { + background-color: transparent; + } } .element-toolbar { diff --git a/app/assets/stylesheets/alchemy/jquery-ui.scss b/app/assets/stylesheets/alchemy/jquery-ui.scss index b9ff9ea3a9..26be6666ad 100644 --- a/app/assets/stylesheets/alchemy/jquery-ui.scss +++ b/app/assets/stylesheets/alchemy/jquery-ui.scss @@ -326,123 +326,6 @@ border-radius: 3px; } -/* - * jQuery UI Tabs 1.8.7 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs#theming - */ - -.ui-tabs { - position: relative; - padding: 0; - margin: 0; - border-style: none; - border-width: 0; -} - -/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed') */ - -.ui-tabs .ui-tabs-nav { - padding: 4px 8px 0; - background: $toolbar-bg-color; - border-radius: 0; - border-bottom: $default-border; - margin: 0; - padding: 0; - height: $tabs-height; -} - -.ui-tabs .ui-tabs-nav li { - list-style: none; - float: left; - position: relative; - height: $tabs-height - $default-border-width; - margin: 0; - border-color: $default-border-color; - border-width: 0; - border-right-width: $default-border-width; - border-radius: 0; - padding: 0; - white-space: nowrap; - background-color: transparent; - font-weight: normal; - - &.ui-tabs-active { - background-color: $light-gray; - height: $tabs-height; - - a { - cursor: default; - } - } -} - -.ui-tabs .ui-tabs-nav li a { - display: block; - text-decoration: none; - padding: 8px 12px 7px; -} - -.ui-tabs .ui-tabs-nav li.ui-tabs-selected { - margin-bottom: 0; - padding-bottom: 1px; - background: $light-gray; -} - -.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, -.ui-tabs .ui-tabs-nav li.ui-state-disabled a, -.ui-tabs .ui-tabs-nav li.ui-state-processing a { - cursor: default; -} - -.ui-tabs .ui-tabs-nav li a, -.ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { - cursor: pointer; -} - -/* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ - -.ui-tabs .ui-tabs-panel { - display: block; - border-width: 0; - background: none; -} - -.ui-tabs .ui-tabs-hide { - display: none !important; -} - -/* UI Tabs Paging */ - -.ui-tabs li.ui-tabs-paging-prev { - border-right-width: 1px; -} - -.ui-tabs li.ui-tabs-paging-next { - float: right !important; - padding: 0 !important; - border-right-width: 0; -} - -.ui-tabs .ui-tabs-nav .ui-tabs-paging-prev a, -.ui-tabs .ui-tabs-nav .ui-tabs-paging-next a { - display: block; - border: 0; - z-index: 2; - padding: 8px; - color: $icon-color; - text-decoration: none; - cursor: pointer; -} - -.ui-tabs .ui-tabs-nav .ui-tabs-paging-disabled { - display: none; -} - /* * jQuery UI Progressbar 1.8.7 * diff --git a/app/assets/stylesheets/alchemy/shoelace.scss b/app/assets/stylesheets/alchemy/shoelace.scss new file mode 100644 index 0000000000..92b15bcade --- /dev/null +++ b/app/assets/stylesheets/alchemy/shoelace.scss @@ -0,0 +1,22 @@ +:root, +:host, +.sl-theme-light { + --sl-font-size-small: #{$base-font-size}; + --sl-color-primary-600: #{$dark-blue}; + --sl-color-neutral-600: #{$text-color}; + --sl-focus-ring-color: #{$focus-color}; + --sl-focus-ring-width: 2px; +} + +sl-tab-group { + --indicator-color: #{$dark-orange}; + --track-color: #{$medium-gray}; + + &::part(base) { + background-color: #{$light-gray}; + } +} + +sl-tab-panel { + --padding: #{4 * $default-padding}; +} diff --git a/app/javascript/alchemy_admin.js b/app/javascript/alchemy_admin.js index a238d4376f..59750c4166 100644 --- a/app/javascript/alchemy_admin.js +++ b/app/javascript/alchemy_admin.js @@ -28,6 +28,9 @@ import "alchemy_admin/components/page_select" import "alchemy_admin/components/spinner" import "alchemy_admin/components/tinymce" import "alchemy_admin/components/tooltip" +import "@shoelace/tab" +import "@shoelace/tab-group" +import "@shoelace/tab-panel" // Global Alchemy object if (typeof window.Alchemy === "undefined") { diff --git a/app/views/alchemy/admin/elements/create.js.erb b/app/views/alchemy/admin/elements/create.js.erb index d5acc21766..1a7da5ca56 100644 --- a/app/views/alchemy/admin/elements/create.js.erb +++ b/app/views/alchemy/admin/elements/create.js.erb @@ -12,7 +12,7 @@ Alchemy.FixedElements.buildTabs('<%= Alchemy.t(:main_content) %>'); } Alchemy.FixedElements.createTab('<%= @element.id %>', '<%= @element.display_name %>'); - $element_area = $('#fixed-element-<%= @element.id %>'); + $element_area = $('[name="fixed-element-<%= @element.id %>"]'); <% elsif @element.parent_element %> $element_area = $('#element_<%= @element.parent_element_id %> > .nestable-elements > .nested-elements'); Alchemy.Buttons.enable('.nestable-elements'); diff --git a/app/views/alchemy/admin/elements/index.html.erb b/app/views/alchemy/admin/elements/index.html.erb index 233cc47fa5..666c429381 100644 --- a/app/views/alchemy/admin/elements/index.html.erb +++ b/app/views/alchemy/admin/elements/index.html.erb @@ -1,31 +1,26 @@ <% if @fixed_elements.any? %> -
    - -
    + + + <%= Alchemy.t(:main_content) %> + + <% @fixed_elements.each do |element| %> + + <%= element.display_name %> + + <% end %> + <%= render @elements.map { |element| Alchemy::ElementEditor.new(element) } %> -
    + <% @fixed_elements.each do |element| %> -
    <%= render Alchemy::ElementEditor.new(element) %> -
    + <% end %> -
    + <% else %>
    <%= render @elements.map { |element| Alchemy::ElementEditor.new(element) } %> diff --git a/app/views/alchemy/admin/elements/new.html.erb b/app/views/alchemy/admin/elements/new.html.erb index ed094dd4cd..3ca385ba05 100644 --- a/app/views/alchemy/admin/elements/new.html.erb +++ b/app/views/alchemy/admin/elements/new.html.erb @@ -1,15 +1,13 @@ <%- if @clipboard_items.blank? -%> <%= render 'form' %> <%- else -%> -
    - -
    + + <%= Alchemy.t('New') %> + <%= Alchemy.t('Paste from clipboard') %> + <%= render 'form' %> -
    -
    + + <%= alchemy_form_for([:admin, @element]) do |f| %> <%= f.hidden_field :page_version_id %> <%= f.hidden_field :parent_element_id, value: @parent_element.try(:id) %> @@ -21,6 +19,6 @@
    <%= f.submit Alchemy.t(:paste) %> <% end %> -
    -
    +
    + <%- end -%> diff --git a/app/views/alchemy/admin/pages/configure.html.erb b/app/views/alchemy/admin/pages/configure.html.erb index f8c56856a4..e051a06769 100644 --- a/app/views/alchemy/admin/pages/configure.html.erb +++ b/app/views/alchemy/admin/pages/configure.html.erb @@ -1,16 +1,14 @@ -
    - -
    + + + <%= Alchemy.t('Properties') %> + + + <%= render 'alchemy/admin/legacy_page_urls/label', count: @page.legacy_urls.size %> + + <%= render 'form' %> -
    -
    + + <%= render 'legacy_urls' %> -
    -
    + + diff --git a/app/views/alchemy/admin/pages/edit.html.erb b/app/views/alchemy/admin/pages/edit.html.erb index 397a87b974..203b074046 100644 --- a/app/views/alchemy/admin/pages/edit.html.erb +++ b/app/views/alchemy/admin/pages/edit.html.erb @@ -193,12 +193,6 @@ Alchemy.SortableElements(<%= @page.id %>, '<%= form_authenticity_token %>'); Alchemy.ElementEditors.init(); Alchemy.SelectBox('.element-editor'); - $('#fixed-elements').tabs().tabs('paging', { - follow: true, - followOnSelect: true, - prevButton: '', - nextButton: '' - }); Alchemy.ElementDirtyObserver('#element_area'); if (window.location.hash) { $(window.location.hash).trigger('FocusElementEditor.Alchemy'); diff --git a/app/views/alchemy/admin/pages/link.html.erb b/app/views/alchemy/admin/pages/link.html.erb index f8d894851c..733e4a51be 100644 --- a/app/views/alchemy/admin/pages/link.html.erb +++ b/app/views/alchemy/admin/pages/link.html.erb @@ -1,20 +1,26 @@ -
    - - - - - -
    + + diff --git a/app/views/alchemy/admin/pages/new.html.erb b/app/views/alchemy/admin/pages/new.html.erb index d7cb8884ce..6f7ce9d630 100644 --- a/app/views/alchemy/admin/pages/new.html.erb +++ b/app/views/alchemy/admin/pages/new.html.erb @@ -1,15 +1,13 @@ <%- if @clipboard_items.blank? -%> <%= render 'new_page_form' %> <%- else -%> -
    - -
    + + <%= Alchemy.t('New page') %> + <%= Alchemy.t('Paste from clipboard') %> + <%= render 'new_page_form' %> -
    -
    + + <%= alchemy_form_for [:admin, @page] do |f| %> <%= f.hidden_field(:parent_id) %>
    @@ -21,6 +19,6 @@ <%= f.input :name %> <%= f.submit Alchemy.t(:paste) %> <% end %> -
    -
    + + <%- end -%> diff --git a/app/views/layouts/alchemy/admin.html.erb b/app/views/layouts/alchemy/admin.html.erb index 8c90c5fba8..b836880973 100644 --- a/app/views/layouts/alchemy/admin.html.erb +++ b/app/views/layouts/alchemy/admin.html.erb @@ -5,6 +5,7 @@ <%= render_alchemy_title %> + <%= csrf_meta_tag %> <%= stylesheet_link_tag('alchemy/admin/all', media: 'screen', 'data-turbo-track' => true) %> diff --git a/config/importmap.rb b/config/importmap.rb index 3e74c3902f..319e4cc656 100644 --- a/config/importmap.rb +++ b/config/importmap.rb @@ -3,6 +3,9 @@ pin "lodash-es/max", to: "https://ga.jspm.io/npm:lodash-es@4.17.21/max.js", preload: true pin "sortablejs", to: "https://ga.jspm.io/npm:sortablejs@1.15.0/modular/sortable.esm.js", preload: true pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true +pin "@shoelace/tab", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.9.0/cdn/components/tab/tab.js", preload: true +pin "@shoelace/tab-group", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.9.0/cdn/components/tab-group/tab-group.js", preload: true +pin "@shoelace/tab-panel", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.9.0/cdn/components/tab-panel/tab-panel.js", preload: true pin "alchemy_admin", to: "alchemy_admin.js", preload: true pin_all_from File.expand_path("../app/javascript/alchemy_admin", __dir__), under: "alchemy_admin" diff --git a/spec/features/admin/edit_elements_feature_spec.rb b/spec/features/admin/edit_elements_feature_spec.rb index e809544575..ef81472ce2 100644 --- a/spec/features/admin/edit_elements_feature_spec.rb +++ b/spec/features/admin/edit_elements_feature_spec.rb @@ -68,7 +68,7 @@ expect(button).to have_content "Add slide" button.click expect(page).to have_select("Element") - expect(page).to have_link("Paste from clipboard") + expect(page).to have_css("[panel='paste_element_tab']") end end @@ -93,7 +93,7 @@ scenario "the add button now opens add element form with the clipboard tab" do find("a.add-nestable-element-button").click expect(page).to have_select("Element") - expect(page).to have_link("Paste from clipboard") + expect(page).to have_css("[panel='paste_element_tab']") end end end diff --git a/spec/features/admin/legacy_page_url_management_spec.rb b/spec/features/admin/legacy_page_url_management_spec.rb index 735efa9fbd..2529458e0c 100644 --- a/spec/features/admin/legacy_page_url_management_spec.rb +++ b/spec/features/admin/legacy_page_url_management_spec.rb @@ -17,7 +17,7 @@ def open_page_properties it "lets a user add a page link" do open_page_properties - click_link "Links" + find("[panel='legacy_urls']").click fill_in "legacy_page_url_urlname", with: "new-urlname" click_button "Add" within "#legacy_page_urls" do @@ -31,7 +31,7 @@ def open_page_properties context "with wrong url format" do it "displays error message" do open_page_properties - click_link "Links" + find("[panel='legacy_urls']").click fill_in "legacy_page_url_urlname", with: "invalid url name" click_button "Add" within "#new_legacy_page_url" do @@ -44,7 +44,7 @@ def open_page_properties before do a_page.legacy_urls.create!(urlname: "a-page-link") open_page_properties - click_link "(1) Link" + find("[panel='legacy_urls']").click end it "lets a user remove a page link" do diff --git a/spec/features/admin/link_overlay_spec.rb b/spec/features/admin/link_overlay_spec.rb index d358c9195b..6a470bc5db 100644 --- a/spec/features/admin/link_overlay_spec.rb +++ b/spec/features/admin/link_overlay_spec.rb @@ -61,7 +61,7 @@ click_link "Link text" end - within "#overlay_tab_internal_link" do + within "[name='overlay_tab_internal_link']" do expect(page).to have_selector("#s2id_internal_link") select2_search(page2.name, from: "Page") click_button "apply" @@ -90,10 +90,10 @@ end within "#overlay_tabs" do - click_link "External" + find("[panel='overlay_tab_external_link']").click end - within "#overlay_tab_external_link" do + within "[name='overlay_tab_external_link']" do expect(page).to have_selector("#external_link") fill_in("URL", with: "https://example.com") click_button "apply" @@ -123,10 +123,10 @@ end within "#overlay_tabs" do - click_link "File" + find("[panel='overlay_tab_file_link']").click end - within "#overlay_tab_file_link" do + within "[name='overlay_tab_file_link']" do expect(page).to have_selector("#file_link") select2(file.name, from: "File") click_button "apply" diff --git a/spec/features/admin/page_creation_feature_spec.rb b/spec/features/admin/page_creation_feature_spec.rb index cf21a3f4af..c7d1e92273 100644 --- a/spec/features/admin/page_creation_feature_spec.rb +++ b/spec/features/admin/page_creation_feature_spec.rb @@ -39,7 +39,7 @@ it "contains tabs for creating a new page and pasting from clipboard" do visit new_admin_page_path - within("#overlay_tabs") { expect(page).to have_selector "#create_page_tab, #paste_page_tab" } + within("#overlay_tabs") { expect(page).to have_selector "[panel='create_page_tab'], [panel='paste_page_tab']" } end context "", js: true do @@ -52,17 +52,17 @@ it "the create page tab is visible by default" do within("#overlay_tabs") do - expect(page).to have_selector("#create_page_tab", visible: true) - expect(page).to have_selector("#paste_page_tab", visible: false) + expect(page).to have_selector("[panel='create_page_tab']", visible: true) + expect(page).to have_selector("[panel='paste_page_tab']", visible: false) end end context "when clicking on an inactive tab" do it "shows that clicked tab" do within("#overlay_tabs") do - click_link("Paste from clipboard") - expect(find("#create_page_tab")).to_not be_visible - expect(find("#paste_page_tab")).to be_visible + find("[panel='paste_page_tab']").click + expect(find("[name='create_page_tab']")).to_not be_visible + expect(find("[name='paste_page_tab']")).to be_visible end end end diff --git a/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js b/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js deleted file mode 100644 index 8d9a4972f7..0000000000 --- a/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +++ /dev/null @@ -1,296 +0,0 @@ -/* - * UI Tabs Paging extension - v1.2.2 (for jQuery 1.9.0 and jQuery UI 1.9.0) - * - * Copyright (c) 2013, http://seyfertdesign.com/jquery/ui-tabs-paging.html - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.tabs.js - */ - -(function($) { - -// overridden ui.tabs functions -var uiTabsFuncs = { - refresh: $.ui.tabs.prototype.refresh, - option: $.ui.tabs.prototype.option -}; - -$.extend($.ui.tabs.prototype, { - paging: function(options) { - var opts = { - tabsPerPage: 0, // Max number of tabs to display at one time. 0 automatically sizing. - nextButton: '»', // Text displayed for next button. - prevButton: '«', // Text displayed for previous button. - follow: false, // When clicking next button, automatically make first tab active. When clicking previous button automatically make last tab active. - cycle: false, // When at end of list, next button returns to first page. When at beginning of list previous button goes to end of list. - activeOnAdd: false, // When new tab is added, make tab active automatically - followOnActive: false // When tab is changed to active, automatically go move to that tab group. - }; - - opts = $.extend(opts, options); - - var self = this, initialized = false, currentPage, - buttonWidth, containerWidth, allTabsWidth, tabWidths, - maxPageWidth, pages, resizeTimer = null, - windowHeight, windowWidth; - - // initialize paging - function init() { - destroy(); - - windowHeight = $(window).height(); - windowWidth = $(window).width(); - - allTabsWidth = 0, currentPage = 0, maxPageWidth = 0, buttonWidth = 0, - pages = new Array(), tabWidths = new Array(), selectedTabWidths = new Array(); - - containerWidth = self.element.width(); - - // loops through LIs, get width of each tab when selected and unselected. - var maxDiff = 0; // the max difference between a selected and unselected tab - self.tabs.each(function(i) { - if (i == self.options.active) { - selectedTabWidths[i] = $(this).outerWidth(true); - tabWidths[i] = self.tabs.eq(i).removeClass('ui-tabs-active').outerWidth(true); - self.tabs.eq(i).addClass('ui-tabs-active'); - maxDiff = Math.min(maxDiff, Math.abs(selectedTabWidths[i] - tabWidths[i])); - allTabsWidth += tabWidths[i]; - } else { - tabWidths[i] = $(this).outerWidth(true); - selectedTabWidths[i] = self.tabs.eq(i).addClass('ui-tabs-active').outerWidth(true); - self.tabs.eq(i).removeClass('ui-tabs-active'); - maxDiff = Math.max(maxDiff, Math.abs(selectedTabWidths[i] - tabWidths[i])); - allTabsWidth += tabWidths[i]; - } - }); - - // fix padding issues with buttons - // TODO determine a better way to handle this - allTabsWidth += maxDiff + 9; - - // if the width of all tables is greater than the container's width, calculate the pages - if (allTabsWidth > containerWidth) { - // create next button - li = $('
  • ') - .addClass('ui-state-default ui-tabs-paging-next') - .append($('') - .click(function() { page('next'); return false; }) - .html(opts.nextButton)); - - self.tablist.append(li); - buttonWidth = li.outerWidth(true); - - // create prev button - li = $('
  • ') - .addClass('ui-state-default ui-tabs-paging-prev') - .append($('') - .click(function() { page('prev'); return false; }) - .html(opts.prevButton)); - self.tablist.prepend(li); - buttonWidth += li.outerWidth(true); - - // TODO determine fix for padding issues to next button - buttonWidth += 19; - - var pageIndex = 0, pageWidth = 0, maxTabPadding = 0; - - // start calculating pageWidths - for (var i = 0; i < tabWidths.length; i++) { - // if first tab of page or selected tab's padding larger than the current max, set the maxTabPadding - if (pageWidth == 0 || selectedTabWidths[i] - tabWidths[i] > maxTabPadding) - maxTabPadding = (selectedTabWidths[i] - tabWidths[i]); - - // if first tab of page, initialize pages variable for page - if (pages[pageIndex] == null) { - pages[pageIndex] = { start: i }; - - } else if ((i > 0 && (i % opts.tabsPerPage) == 0) || (tabWidths[i] + pageWidth + buttonWidth + 12) > containerWidth) { - if ((pageWidth + maxTabPadding) > maxPageWidth) - maxPageWidth = (pageWidth + maxTabPadding); - pageIndex++; - pages[pageIndex] = { start: i }; - pageWidth = 0; - } - pages[pageIndex].end = i+1; - pageWidth += tabWidths[i]; - if (i == self.options.active) currentPage = pageIndex; - } - if ((pageWidth + maxTabPadding) > maxPageWidth) - maxPageWidth = (pageWidth + maxTabPadding); - - // hide all tabs then show tabs for current page - self.tabs.hide().slice(pages[currentPage].start, pages[currentPage].end).show(); - if (currentPage == (pages.length - 1) && !opts.cycle) - disableButton('next'); - if (currentPage == 0 && !opts.cycle) - disableButton('prev'); - - // calculate the right padding for the next button - buttonPadding = containerWidth - maxPageWidth - buttonWidth; - if (buttonPadding > 0) - $('.ui-tabs-paging-next', self.element).css({ paddingRight: buttonPadding + 'px' }); - } else { - destroy(); - } - - $(window).bind('resize', handleResize); - - initialized = true; - } - - // handles paging forward and backward - function page(direction) { - currentPage = currentPage + (direction == 'prev'?-1:1); - - if ((direction == 'prev' && currentPage < 0 && opts.cycle) || - (direction == 'next' && currentPage >= pages.length && !opts.cycle)) - currentPage = pages.length - 1; - else if ((direction == 'prev' && currentPage < 0) || - (direction == 'next' && currentPage >= pages.length && opts.cycle)) - currentPage = 0; - - var start = pages[currentPage].start; - var end = pages[currentPage].end; - self.tabs.hide().slice(start, end).show(); - - if (direction == 'prev') { - enableButton('next'); - if (opts.follow && (self.options.active < start || self.options.active > (end-1))) self.option('active', end-1); - if (!opts.cycle && start <= 0) disableButton('prev'); - } else { - enableButton('prev'); - if (opts.follow && (self.options.active < start || self.options.active > (end-1))) self.option('active', start); - if (!opts.cycle && end >= self.tabs.length) disableButton('next'); - } - } - - // change styling of next/prev buttons when disabled - function disableButton(direction) { - $('.ui-tabs-paging-'+direction, self.element).addClass('ui-tabs-paging-disabled'); - } - - function enableButton(direction) { - $('.ui-tabs-paging-'+direction, self.element).removeClass('ui-tabs-paging-disabled'); - } - - // special function defined to handle IE resize issues - function handleResize() { - if (resizeTimer) clearTimeout(resizeTimer); - - if (windowHeight != $(window).height() || windowWidth != $(window).width()) - { - resizeTimer = setTimeout(init, 100); - } - } - - // remove all paging related changes and events - function destroy() { - // remove buttons - $('.ui-tabs-paging-next', self.element).remove(); - $('.ui-tabs-paging-prev', self.element).remove(); - - // show all tabs - self.tabs.show(); - - initialized = false; - - $(window).unbind('resize', handleResize); - } - - - - // ------------- OVERRIDDEN PUBLIC FUNCTIONS ------------- - self.option = function(optionName, value) { - var retVal = uiTabsFuncs.option.apply(this, [optionName, value]); - - // if "followOnActive" is true, then move page when selection changes - if (optionName == "active") - { - // if paging is not initialized or it is not configured to - // change pages when a new tab is active, then do nothing - if (!initialized || !opts.followOnActive) - return retVal; - - // find the new page based on index of the active tab - for (var i in pages) { - var start = pages[i].start; - var end = pages[i].end; - if (value >= start && value < end) { - // if the the active tab is not within the currentPage of tabs, then change pages - if (i != currentPage) { - this.tabs.hide().slice(start, end).show(); - - currentPage = parseInt(i); - if (currentPage == 0) { - enableButton('next'); - if (!opts.cycle && start <= 0) disableButton('prev'); - } else { - enableButton('prev'); - if (!opts.cycle && end >= this.tabs.length) disableButton('next'); - } - } - break; - } - } - } - - return retVal; - } - - self.refresh = function() { - if (initialized) - { - destroy(); - - uiTabsFuncs.refresh.apply(this); - - // re-initialize paging buttons - init(); - } - - uiTabsFuncs.refresh.apply(this); - } - - - // ------------- PUBLIC FUNCTIONS ------------- - $.extend($.ui.tabs.prototype, { - // public function for removing paging - pagingDestroy: function() { - destroy(); - return this; - }, - - // public function to handle resizes that are not on the window - pagingResize: function() { - init(); - return this; - } - }); - - // initialize on startup! - init(); - } -}); - - -})(jQuery);