first commit

This commit is contained in:
root
2026-03-14 09:49:00 +00:00
commit 708ff116e1
1958 changed files with 1718027 additions and 0 deletions

331
www/CHANGELOG Normal file
View File

@@ -0,0 +1,331 @@
Version 7.8.6 - 2026-03-02
--------------------------
* Bug fixes (see mercurial logs for details)
Version 7.8.5 - 2026-02-18
--------------------------
* Bug fixes (see mercurial logs for details)
Version 7.8.4 - 2026-02-01
--------------------------
* Bug fixes (see mercurial logs for details)
Version 7.8.3 - 2026-01-15
--------------------------
* Bug fixes (see mercurial logs for details)
Version 7.8.2 - 2026-01-02
--------------------------
* Bug fixes (see mercurial logs for details)
Version 7.8.1 - 2025-12-20
--------------------------
* Bug fixes (see mercurial logs for details)
Version 7.8.0 - 2025-12-15
--------------------------
* Bug fixes (see mercurial logs for details)
* Allow users to subscribe to chats
* Manage user notification
* Add search on empty relation field to domain parser
* Escape completion content with custom format (issue14363)
* Use sandboxed iframe to display document (issue14290)
* Add support for multiple button in the tree view
* Support shortcuts on modal
Version 7.6.0 - 2025-04-28
--------------------------
* Bug fixes (see mercurial logs for details)
* Allow column widths to be reset
* Allow column resizing
* Add simple chat widget on sidebar
* Support color as type of icon and image
* Support color widget on form view
Version 7.4.0 - 2024-11-04
--------------------------
* Bug fixes (see mercurial logs for details)
* Add restore button on Many2Many
* Keep CSV export window opened
* Remove favorite management
* Retry JSON-RPC requests on Service Unavailable
* Allow resizing the attachment preview panel
* Set focus on search entry after search
* Support language suffix in CSV export
* Close tab with mouse middle click
* Support language suffix in CSV import
Version 7.2.0 - 2024-04-29
--------------------------
* Bug fixes (see mercurial logs for details)
* Read xxx2Many fields using the dotted notation
* Display XML ID on Log window
* Use operators when converting PYSON to string
* Add DnD on binary and image widgets
* Allow resetting forgotten password
Version 7.0.0 - 2023-10-30
--------------------------
* Bug fixes (see mercurial logs for details)
* Support create record from autocomplete
* Use grid layout for form container
* Support scanning code
* Reset search offset when domain has changed
* Add a canonicalize function for domains
* Add menu to copy selected record from tree view to clipboard
* Support PYSON comparison of timedelta
* Support encoding timedelta into PYSON TimeDelta
* Eagerly read string value of multiselection fields
* Use locale timezone for CSV in locale format
Version 6.8.0 - 2023-05-01
--------------------------
* Bug fixes (see mercurial logs for details)
* Include events to logs
* Support scroll time on calendar view
* Save and Restore tree state on List Form
* Do record (pre)validation and saving on selection change for list-form views
* Eagerly read string value of selection fields
* Do not select first record by default
* Use ``&`` and ``|`` as boolean operator in search widget
* Use toggle button and label on translate dialog
* Support border type of images
* Manage domain on id in single value list as unique
* Do not validate domain nor enforce uniqueness for empty fields unless they're required or invisible
* Display the number of selected records on xxx2Many
Version 6.6.0 - 2022-10-31
--------------------------
* Bug fixes (see mercurial logs for details)
* Support authentication services
* Check server version
Version 6.4.0 - 2022-05-02
* Bug fixes (see mercurial logs for details)
* Support notification message
* Allow Reference to be edited from tree view
* Set ECMAScript version to 6
* Manage optional column
* Display the number of selected records
* Humanize the count result
* Add limit to search_count
* Call view_get for board view
* Limit board action domain to active id and ids
* Manage creatable attribute of view
Version 6.2.0 - 2021-11-01
* Bug fixes (see mercurial logs for details)
* Support grouping attribute
* Add expander on tree to fold or unfold selected rows
* Support monetary and symbol field attributes
* Support digits from relation field
* Add accesskey to widgets and buttons
* Support Binary field in CSV import/export
Version 6.0.0 - 2021-05-03
* Bug fixes (see mercurial logs for details)
* Use appropriate types for email and url widgets
* Add completion on xxx2Many and Dict
* Add attachment preview
* Support document widget
* Support icon of type URL
* Allow sending email with existing attachments
* Add paths and model context to action data
* Add indentation in CSV export of tree
* Manage which records to use for actions
* Add drag and drop on CSV export and import
* Remove tempusdominus dependency
* Handle device cookie
* Add breadcrumb as title of window form
* Manage help for each selection
* Display revision on dialog
* Support empty value for timedelta converter
* Unify PYSON string format
Version 5.8.0 - 2020-11-02
* Bug fixes (see mercurial logs for details)
* Format timedelta in CSV export
* Manage symbol widget
* Fallback to model name as title
* Set treeview footer sticky on bottom
* Add get, in_ and contains methods to PYSON
* Manage deletable and writable state
* Support email template
* Always encode CSV export in UTF-8
* Use tempusdominus and Popper for date time picker
* Support PYSON comparison of date and datetime
* Customize bootstrap default style
* Set field's name as input's name attribute
* Position copied records based on order
* Sanitize translated RichtText fields content (issue9453)
* Allow configuration of default colors for graph and calendar
* Sanitize RichtText fields content (issue9405)
* Escape external string (issue9394)
* Keep context in sessionStorage
* Use existing context for get_preferences
* Escape external strings (issue9351)
* Add context to export URL
* Allow changes to editable tree checkboxes without first selecting the line
Version 5.6.0 - 2020-05-04
* Bug fixes (see mercurial logs for details)
* Support link button on form
* Add URL for the current export
* Add option to export listed records
* Set treeview header sticky on top
* Add noreferrer noopener to external URL (issue9089)
* Manage readonly dates in calendar view
* Manage editable on calendar view
* Manage named separator as label
* Add MultiSelection entry to Dict field
* Position new record based on order
* Reset display_size of TreeView when group is cleared or changed
* Allow relation field to be selected in CSV export
* Hide empty cell on small screen
* Support validate attribute of wizard's Button
* Add infinite scroll
Version 5.4.0 - 2019-11-04
* Bug fixes (see mercurial logs for details)
* Support visual context on tree view
* Support multiselection field
* Support dot notation on PYSON Eval
* Manage sequence
* Add drag and drop on tree views
* Support expand on column
* Set minimal width for columns
* Order Dict keys by sequence
* Support relation fields in domain parser
* Add view modified
* Add Dict widget for tree view
Version 5.2.0 - 2019-05-06
* Bug fixes (see mercurial logs for details)
* Add domain inversion for reference fields
* Add list-form view
* Support HTML widget
* Use locale format for data export
* Add day view on calendar
* Add CSV exports into print toolbar
* Display unread and total of notes
* Use resources method
* Rename roundup.url configuration to bug.url
* Use separate XML parser in Views
* Add range selection with Shift-click
* Use between numbers in filter box
* Fill 'to' with 'from' value on filter box
* Add tab domain in URL
* Use properties
* Allow sao classes to use javascript properties
* Improve layout of CSV import/export
* Add support for height and width on notebook
* Use tab key for tab navigation
* Use record and field properties of widget instead of method arguments
* Reduce offset when no search result
* Add support for plugins
* Add support for expand, height and width attributes
* Add drag & drop support on attachment button
Version 5.0.0 - 2018-10-01
* Bug fixes (see mercurial logs for details)
* Prevent similar tab
* Remove dialog for input file
* Use dropdown for attachment
* Manage icons in input
* Support RTL language direction
* Apply factor on domain parser
* Use tab name in CSV Export/Import
* Add bus management
* Load custom CSS and Javascript
* New icons
* Support timestamp field
* Validate dictionary items
* Add (i)like support to domain inversion
* Improve loading strategy by using views
* Add support of width attribute on tree view
* Use non conflicting keyboard shortcuts
* Use the context to get the suffix of window name
* Call on_change methods after setting default dtstart on calendar view
* Allow to open in new tab Many2One and Reference with CTRL key
* Store session in browser storage
* Increase the space available for tab list
* Allow to toggle menu on large screen
* Manage URL and history
Version 4.8.0 - 2018-04-23
* Bug fixes (see mercurial logs for details)
* Manage active field on search widget
* Add position and length on list view
* Reset record to its original state when discarding the popup window
* Add support of expand attribute on group tag
* Add the context model name in the screen context
* Add sum of records on list view
* Add shortcuts to Date and DateTime widgets
* Use limit to expand tree
* Use spellcheck and lang attributes for textbox widget
* Support icon on page
* Add keyword attribute to button tag
* Support field name on image tag
* Use input number and toLocaleString for numeric fields
* Show related record names for all windows
* Allow to edit Many2One from tree view
* Use translated values when exporting Reference and Selection fields
Version 4.6.0 - 2017-10-30
* Bug fixes (see mercurial logs for details)
* Allow to export model and record name of Reference fields
* Re-position buttons on Binary/Image widget
* Set focus on first visible input when modal is shown
* Improve treeview headers
* Add keyboard shortcuts
* Update states of both toolbar and menu
* Improve toolbar order
* Use login details in title
Version 4.4.0 - 2017-05-01
* Bug fixes (see mercurial logs for details)
* Manage help attribute on tree views
* Manage color attribute on graph view
* Add support for size on Many2Many
* Allow to show plain text in password field
Version 4.2.0 - 2016-11-28
* Bug fixes (see mercurial logs for details)
* Add PYSON Widget
* Add CSV Import/Export
* Manage translated field
* Add favorites menu
* Show records names in wizard title
* Add support for datetime_field to Many2One, Reference
* Add calendar view
* Move info-bar to the top
* Add noeval to PYSONDecoder
* Add support for pyson_order on action window
* Make datetimepicker locale aware
* Restore tab default order when no manual change
* Add support for column sorting
* Manage confirm attribute on buttons
* Call autocompletion when setting record value
* Limit readonly state for xxx2Many
* Simplify login with single database
* Show records names in relate window title
* Add support for count on Action Window Domains
* Manage custom login process
* Add erase on Many2One
* Re-position icons on Many2One widget
Version 4.0.0 - 2016-05-02
* Bug fixes (see mercurial logs for details)
* Timedelta uses 30 days for month
* Manage context model of ir.action.act_window
* Add Note
Version 3.8.0 - 2015-11-02
* Initial release

21
www/COPYRIGHT Normal file
View File

@@ -0,0 +1,21 @@
Copyright (C) 2012-2025 Nicolas Évrard.
Copyright (C) 2012-2026 Cédric Krier.
Copyright (C) 2012-2014 Bertrand Chenal.
Copyright (C) 2012-2026 B2CK SPRL.
Copyright (C) 2019 Jitbit.
Copyright (C) 2013 Thomas Park
Copyright (C) 2020-2021 Maxime Richez
Copyright (C) 2020-2021 SALUC SA
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

146
www/Gruntfile.js Normal file
View File

@@ -0,0 +1,146 @@
module.exports = function(grunt) {
var _ = grunt.util._;
var locales = ["bg", "ca", "cs", "de", "es", "es_419", "fr", "fa", "hu",
"it", "lo", "lt", "nl", "pl", "pt", "ru", "sl", "zh_CN"];
var jsfiles = [
'src/sao.js',
'src/rpc.js',
'src/pyson.js',
'src/session.js',
'src/common.js',
'src/model.js',
'src/tab.js',
'src/screen.js',
'src/view.js',
'src/view/form.js',
'src/view/tree.js',
'src/view/graph.js',
'src/view/calendar.js',
'src/view/list_form.js',
'src/action.js',
'src/window.js',
'src/wizard.js',
'src/board.js',
'src/bus.js',
'src/chat.js',
'src/notification.js',
'src/plugins.js',
'src/html_sanitizer.js'
];
var less_paths = [
'src',
'bower_components',
'bower_components/bootstrap',
'bower_components/bootstrap/less',
'bower_components/bootstrap-rtl-ondemand/less',
];
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
shell: {
options: {
failOnError: true
},
msgmerge: {
command: _.map(locales, function(locale) {
var po = "locale/" + locale + ".po";
return (
"msgmerge " +
"-U " + po + " " +
"--no-location " +
"locale/messages.pot;");
}).join("")
},
xgettext: {
command: (
"xgettext " +
"--language=JavaScript --from-code=UTF-8 " +
"--omit-header --no-location " +
"-o locale/messages.pot " +
jsfiles.join(" "))
}
},
po2json: {
options: {
format: 'raw'
},
all: {
src: ['locale/*.po'],
dest: 'locale/'
}
},
concat: {
dist: {
src: jsfiles,
dest: 'dist/<%= pkg.name %>.js'
}
},
less: {
'default': {
options: {
paths: less_paths,
},
files: {
'dist/<%= pkg.name %>.css': 'src/sao.less'
}
}
},
watch: {
scripts: {
files: ['src/**/*.js'],
tasks: ['concat']
},
styles: {
files: ['src/*.less'],
tasks: 'less'
},
translations: {
files: ['locale/*.po'],
tasks: 'po2json'
}
},
qunit: {
options: {
timeout: 300000,
puppeteer: {
headless: true,
args: [
'--no-sandbox',
],
env: {
TZ: 'UTC',
},
},
},
all: ['tests/*.html']
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-po2json');
grunt.loadNpmTasks('grunt-qunit-junit');
grunt.registerTask('default', 'Build for production.', function() {
grunt.task.run(['concat', 'less', 'po2json']);
});
grunt.registerTask('watch', 'Watch development', function() {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.task.run(['watch']);
});
grunt.registerTask('msgmerge', 'Update locale messages.', function() {
grunt.loadNpmTasks('grunt-shell');
grunt.task.run(['shell:msgmerge']);
});
grunt.registerTask('xgettext', ' Extracts translatable messages', function() {
grunt.loadNpmTasks('grunt-shell');
grunt.task.run(['shell:xgettext']);
});
grunt.registerTask('test', 'Run tests', function() {
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.task.run(['concat', 'less', 'qunit_junit', 'qunit']);
});
};

674
www/LICENSE Normal file
View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

29
www/README.md Normal file
View File

@@ -0,0 +1,29 @@
sao
===
Prerequisites
-------------
* Node.js 0.8.0 or later (http://nodejs.org/)
Installation
------------
Once you've downloaded and unpacked the sao source release, enter the directory
where the archive was unpacked, and run:
$ npm install --production --legacy-peer-deps
Development
...........
For development, you have to run instead:
$ npm install --legacy-peer-deps
$ grunt
Setup
-----
Note that the entry `root` in the section `[web]` of `trytond.conf` must be set
to the directory where the package was unpacked.

29
www/bower.json Normal file
View File

@@ -0,0 +1,29 @@
{
"name": "sao",
"version": "0.0.0",
"authors": [
"Tryton"
],
"description": "Web client for Tryton",
"license": "GPL",
"homepage": "http://www.tryton.org/",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "^3",
"bootstrap": "^3.3.7",
"moment": "^2.10",
"gettext.js": "^2",
"c3": "^0.7",
"papaparse": "^5.0",
"fullcalendar": "^3.10.2",
"mousetrap": "^1.6",
"bootstrap-rtl-ondemand": "^3.3.4-ondemand",
"Sortable": "sortablejs#^1.8.4"
}
}

View File

@@ -0,0 +1,40 @@
{
"name": "Sortable",
"main": [
"Sortable.js"
],
"homepage": "http://SortableJS.github.io/Sortable/",
"authors": [
"RubaXa <ibnRubaXa@gmail.com>",
"owenm <owen23355@gmail.com>"
],
"description": "JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery required. Supports Meteor, AngularJS, React, Polymer, Vue, Knockout and any CSS library, e.g. Bootstrap.",
"keywords": [
"sortable",
"reorder",
"list",
"html5",
"drag",
"and",
"drop",
"dnd",
"web-components"
],
"license": "MIT",
"ignore": [
"node_modules",
"bower_components",
"test",
"tests"
],
"version": "1.15.7",
"_release": "1.15.7",
"_resolution": {
"type": "version",
"tag": "1.15.7",
"commit": "031649b8116565e02419e8aa2d252d7d8c82b9da"
},
"_source": "https://github.com/RubaXa/Sortable.git",
"_target": "^1.8.4",
"_originalSource": "sortablejs"
}

View File

@@ -0,0 +1,33 @@
version: 2.0
jobs:
build:
docker:
- image: circleci/node:10.16-browsers
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-
- run: npm install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: npm run build:umd
- run:
name: Compatibility Test
command: |
if [ -z "$CIRCLE_PR_NUMBER" ];
then
npm run test:compat
fi
- run: npm run test
- store_test_results:
path: /tmp/test-results

View File

@@ -0,0 +1,15 @@
# editorconfig.org
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_style = space

View File

@@ -0,0 +1,73 @@
---
name: Bug report
about: Create a report to help us improve
title: "[bug] "
labels: ""
assignees: ""
---
<!--
PLEASE READ BEFORE POSTING YOUR ISSUE!
If your issue is related to a framework or @types/sortablejs,
please post an issue on it's relevant repository instead:
- Angular
- 2.0+: https://github.com/SortableJS/angular-sortablejs/issues
- legacy: https://github.com/SortableJS/angular-legacy-sortablejs/issues
- React
- ES2015+: https://github.com/SortableJS/react-sortablejs/issues
- mixin: https://github.com/SortableJS/react-mixin-sortablejs/issues
- Polymer: https://github.com/SortableJS/polymer-sortablejs/issues
- Knockout: https://github.com/SortableJS/knockout-sortablejs/issues
- Meteor: https://github.com/SortableJS/meteor-sortablejs/issues
If it is a bug found from using one of these, please link to the related issue.
-->
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Information**
<!-- This is required. Issues without this critical information will be closed. -->
Versions - Look in your `package.json` for this information:
sortablejs = ^x.x.x
@types/sortablejs = ^x.x.x
**Additional context**
Add any other context about the problem here.
**Reproduction**
codesandbox: <your_url_here>
<!--
Providing a codesandbox really helps us understand your issue.
Bugs with codesandboxes attached are likely to be resolved more quickly than others.
Once you've created a public codesandbox, please paste a link in here
Here are some templates to get you started.
- Javascript: https://codesandbox.io/s/sortablejs-javascript-jy3tl?file=/src/index.js
- Typescript: https://codesandbox.io/s/sortablejs-typescript-6it9n?file=/src/index.ts
-->

View File

@@ -0,0 +1,48 @@
---
name: Custom issue template
about: Not a feature request or a bug report. Usually questions, queries or concerns
title: ""
labels: ""
assignees: ""
---
**Custom**
<!--
PLEASE READ BEFORE POSTING YOUR ISSUE!
If your issue is related to a framework or @types/sortablejs,
please post an issue on it's relevant repository instead:
- Angular
- 2.0+: https://github.com/SortableJS/angular-sortablejs/issues
- legacy: https://github.com/SortableJS/angular-legacy-sortablejs/issues
- React
- ES2015+: https://github.com/SortableJS/react-sortablejs/issues
- mixin: https://github.com/SortableJS/react-mixin-sortablejs/issues
- Polymer: https://github.com/SortableJS/polymer-sortablejs/issues
- Knockout: https://github.com/SortableJS/knockout-sortablejs/issues
- Meteor: https://github.com/SortableJS/meteor-sortablejs/issues
If it is a bug found from using one of these, please link to the related issue.
-->
**Reproduction**
codesandbox: <your_url_here>
<!--
Providing a codesandbox really helps us understand your issue.
Bugs with codesandboxes attached are likely to be resolved more quickly than others.
Once you've created a public codesandbox, please paste a link in here
Here are some templates to get you started.
- Javascript: https://codesandbox.io/s/sortablejs-javascript-jy3tl?file=/src/index.js
- Typescript: https://codesandbox.io/s/sortablejs-typescript-6it9n?file=/src/index.ts
-->

View File

@@ -0,0 +1,41 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[feature] "
labels: ""
assignees: ""
---
<!--
PLEASE READ BEFORE POSTING YOUR ISSUE!
If your issue is related to a framework or @types/sortablejs,
please post an issue on it's relevant repository instead:
- Angular
- 2.0+: https://github.com/SortableJS/angular-sortablejs/issues
- legacy: https://github.com/SortableJS/angular-legacy-sortablejs/issues
- React
- ES2015+: https://github.com/SortableJS/react-sortablejs/issues
- mixin: https://github.com/SortableJS/react-mixin-sortablejs/issues
- Polymer: https://github.com/SortableJS/polymer-sortablejs/issues
- Knockout: https://github.com/SortableJS/knockout-sortablejs/issues
- Meteor: https://github.com/SortableJS/meteor-sortablejs/issues
If it is a bug found from using one of these, please link to the related issue.
-->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,6 @@
node_modules
mock.png
.*.sw*
.build*
jquery.fn.*
.idea/

25
www/bower_components/Sortable/.jshintrc vendored Normal file
View File

@@ -0,0 +1,25 @@
{
"strict": false,
"newcap": false,
"node": true,
"expr": true,
"supernew": true,
"laxbreak": true,
"esversion": 9,
"white": true,
"globals": {
"define": true,
"test": true,
"expect": true,
"module": true,
"asyncTest": true,
"start": true,
"ok": true,
"equal": true,
"notEqual": true,
"deepEqual": true,
"window": true,
"document": true,
"performance": true
}
}

View File

@@ -0,0 +1,7 @@
{
"speed": 0.4,
"reporter": {
"name": "xunit",
"output": "/tmp/test-results/res.xml"
}
}

View File

@@ -0,0 +1,26 @@
# Contribution Guidelines
### Issue
1. Try [master](https://github.com/SortableJS/Sortable/tree/master/)-branch, perhaps the problem has been solved;
2. [Use the search](https://github.com/SortableJS/Sortable/search?type=Issues&q=problem), maybe already have an answer;
3. If not found, create example on [jsbin.com (draft)](https://jsbin.com/kamiwez/edit?html,js,output) and describe the problem.
---
### Pull Request
1. Only request to merge with the [master](https://github.com/SortableJS/Sortable/tree/master/)-branch.
2. Only modify source files, **do not commit the resulting build**
### Setup
1. Fork the repo on [github](https://github.com)
2. Clone locally
3. Run `npm i` in the local repo
### Building
- For development, build the `./Sortable.js` file using the command `npm run build:umd:watch`
- To build everything and minify it, run `npm run build`
- Do not commit the resulting builds in any pull request they will be generated at release

21
www/bower_components/Sortable/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 All contributors to Sortable
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.

829
www/bower_components/Sortable/README.md vendored Normal file
View File

@@ -0,0 +1,829 @@
# Sortable &nbsp; [![Financial Contributors on Open Collective](https://opencollective.com/Sortable/all/badge.svg?label=financial+contributors)](https://opencollective.com/Sortable) [![CircleCI](https://circleci.com/gh/SortableJS/Sortable.svg?style=svg)](https://circleci.com/gh/SortableJS/Sortable) [![DeepScan grade](https://deepscan.io/api/teams/3901/projects/5666/branches/43977/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=3901&pid=5666&bid=43977) [![](https://data.jsdelivr.com/v1/package/npm/sortablejs/badge)](https://www.jsdelivr.com/package/npm/sortablejs) [![npm](https://img.shields.io/npm/v/sortablejs.svg)](https://www.npmjs.com/package/sortablejs)
Sortable is a JavaScript library for reorderable drag-and-drop lists.
Demo: http://sortablejs.github.io/Sortable/
[<img width="250px" src="https://raw.githubusercontent.com/SortableJS/Sortable/HEAD/st/saucelabs.svg?sanitize=true">](https://saucelabs.com/)
## Features
* Supports touch devices and [modern](http://caniuse.com/#search=drag) browsers (including IE9)
* Can drag from one list to another or within the same list
* CSS animation when moving items
* Supports drag handles *and selectable text* (better than voidberg's html5sortable)
* Smart auto-scrolling
* Advanced swap detection
* Smooth animations
* [Multi-drag](https://github.com/SortableJS/Sortable/tree/master/plugins/MultiDrag) support
* Support for CSS transforms
* Built using native HTML5 drag and drop API
* Supports
* [Meteor](https://github.com/SortableJS/meteor-sortablejs)
* Angular
* [2.0+](https://github.com/SortableJS/angular-sortablejs)
* [1.&ast;](https://github.com/SortableJS/angular-legacy-sortablejs)
* React
* [ES2015+](https://github.com/SortableJS/react-sortablejs)
* [Mixin](https://github.com/SortableJS/react-mixin-sortablejs)
* [Knockout](https://github.com/SortableJS/knockout-sortablejs)
* [Polymer](https://github.com/SortableJS/polymer-sortablejs)
* [Vue](https://github.com/SortableJS/Vue.Draggable)
* [Ember](https://github.com/SortableJS/ember-sortablejs)
* Supports any CSS library, e.g. [Bootstrap](#bs)
* Simple API
* Support for [plugins](#plugins)
* [CDN](#cdn)
* No jQuery required (but there is [support](https://github.com/SortableJS/jquery-sortablejs))
* Typescript definitions at `@types/sortablejs`
<br/>
### Articles
* [Dragging Multiple Items in Sortable](https://github.com/SortableJS/Sortable/wiki/Dragging-Multiple-Items-in-Sortable) (April 26, 2019)
* [Swap Thresholds and Direction](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction) (December 2, 2018)
* [Sortable v1.0 — New capabilities](https://github.com/SortableJS/Sortable/wiki/Sortable-v1.0-—-New-capabilities/) (December 22, 2014)
* [Sorting with the help of HTML5 Drag'n'Drop API](https://github.com/SortableJS/Sortable/wiki/Sorting-with-the-help-of-HTML5-Drag'n'Drop-API/) (December 23, 2013)
<br/>
### Getting Started
Install with NPM:
```bash
npm install sortablejs --save
```
Install with Bower:
```bash
bower install --save sortablejs
```
Import into your project:
```js
// Default SortableJS
import Sortable from 'sortablejs';
// Core SortableJS (without default plugins)
import Sortable from 'sortablejs/modular/sortable.core.esm.js';
// Complete SortableJS (with all plugins)
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
```
Cherrypick plugins:
```js
// Cherrypick extra plugins
import Sortable, { MultiDrag, Swap } from 'sortablejs';
Sortable.mount(new MultiDrag(), new Swap());
// Cherrypick default plugins
import Sortable, { AutoScroll } from 'sortablejs/modular/sortable.core.esm.js';
Sortable.mount(new AutoScroll());
```
---
### Usage
```html
<ul id="items">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
```
```js
var el = document.getElementById('items');
var sortable = Sortable.create(el);
```
You can use any element for the list and its elements, not just `ul`/`li`. Here is an [example with `div`s](https://jsbin.com/visimub/edit?html,js,output).
---
### Options
```js
var sortable = new Sortable(el, {
group: "name", // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }
sort: true, // sorting inside list
delay: 0, // time in milliseconds to define when the sorting should start
delayOnTouchOnly: false, // only delay if user is using touch
touchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag event
disabled: false, // Disables the sortable if set to true.
store: null, // @see Store
animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
easing: "cubic-bezier(1, 0, 0, 1)", // Easing for animation. Defaults to null. See https://easings.net/ for examples.
handle: ".my-handle", // Drag handle selector within list items
filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function)
preventOnFilter: true, // Call `event.preventDefault()` when triggered `filter`
draggable: ".item", // Specifies which items inside the element should be draggable
dataIdAttr: 'data-id', // HTML attribute that is used by the `toArray()` method
ghostClass: "sortable-ghost", // Class name for the drop placeholder
chosenClass: "sortable-chosen", // Class name for the chosen item
dragClass: "sortable-drag", // Class name for the dragging item
swapThreshold: 1, // Threshold of the swap zone
invertSwap: false, // Will always use inverted swap zone if set to true
invertedSwapThreshold: 1, // Threshold of the inverted swap zone (will be set to swapThreshold value by default)
direction: 'horizontal', // Direction of Sortable (will be detected automatically if not given)
forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in
fallbackClass: "sortable-fallback", // Class name for the cloned DOM Element when using forceFallback
fallbackOnBody: false, // Appends the cloned DOM Element into the Document's Body
fallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag.
dragoverBubble: false,
removeCloneOnHide: true, // Remove the clone element when it is not showing, rather than just hiding it
emptyInsertThreshold: 5, // px, distance mouse must be from empty sortable to insert drag element into it
setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent
},
// Element is chosen
onChoose: function (/**Event*/evt) {
evt.oldIndex; // element index within parent
},
// Element is unchosen
onUnchoose: function(/**Event*/evt) {
// same properties as onEnd
},
// Element dragging started
onStart: function (/**Event*/evt) {
evt.oldIndex; // element index within parent
},
// Element dragging ended
onEnd: function (/**Event*/evt) {
var itemEl = evt.item; // dragged HTMLElement
evt.to; // target list
evt.from; // previous list
evt.oldIndex; // element's old index within old parent
evt.newIndex; // element's new index within new parent
evt.oldDraggableIndex; // element's old index within old parent, only counting draggable elements
evt.newDraggableIndex; // element's new index within new parent, only counting draggable elements
evt.clone // the clone element
evt.pullMode; // when item is in another sortable: `"clone"` if cloning, `true` if moving
},
// Element is dropped into the list from another list
onAdd: function (/**Event*/evt) {
// same properties as onEnd
},
// Changed sorting within list
onUpdate: function (/**Event*/evt) {
// same properties as onEnd
},
// Called by any change to the list (add / update / remove)
onSort: function (/**Event*/evt) {
// same properties as onEnd
},
// Element is removed from the list into another list
onRemove: function (/**Event*/evt) {
// same properties as onEnd
},
// Attempt to drag a filtered element
onFilter: function (/**Event*/evt) {
var itemEl = evt.item; // HTMLElement receiving the `mousedown|tapstart` event.
},
// Event when you move an item in the list or between lists
onMove: function (/**Event*/evt, /**Event*/originalEvent) {
// Example: https://jsbin.com/nawahef/edit?js,output
evt.dragged; // dragged HTMLElement
evt.draggedRect; // DOMRect {left, top, right, bottom}
evt.related; // HTMLElement on which have guided
evt.relatedRect; // DOMRect
evt.willInsertAfter; // Boolean that is true if Sortable will insert drag element after target by default
originalEvent.clientY; // mouse position
// return false; — for cancel
// return -1; — insert before target
// return 1; — insert after target
// return true; — keep default insertion point based on the direction
// return void; — keep default insertion point based on the direction
},
// Called when creating a clone of element
onClone: function (/**Event*/evt) {
var origEl = evt.item;
var cloneEl = evt.clone;
},
// Called when dragging element changes position
onChange: function(/**Event*/evt) {
evt.newIndex // most likely why this event is used is to get the dragging element's current index
// same properties as onEnd
}
});
```
---
#### `group` option
To drag elements from one list into another, both lists must have the same `group` value.
You can also define whether lists can give away, give and keep a copy (`clone`), and receive elements.
* name: `String` — group name
* pull: `true|false|["foo", "bar"]|'clone'|function` — ability to move from the list. `clone` — copy the item, rather than move. Or an array of group names which the elements may be put in. Defaults to `true`.
* put: `true|false|["baz", "qux"]|function` — whether elements can be added from other lists, or an array of group names from which elements can be added.
* revertClone: `boolean` — revert cloned element to initial position after moving to a another list.
Demo:
- https://jsbin.com/hijetos/edit?js,output
- https://jsbin.com/nacoyah/edit?js,output — use of complex logic in the `pull` and` put`
- https://jsbin.com/bifuyab/edit?js,output — use `revertClone: true`
---
#### `sort` option
Allow sorting inside list.
Demo: https://jsbin.com/jayedig/edit?js,output
---
#### `delay` option
Time in milliseconds to define when the sorting should start.
Unfortunately, due to browser restrictions, delaying is not possible on IE or Edge with native drag & drop.
Demo: https://jsbin.com/zosiwah/edit?js,output
---
#### `delayOnTouchOnly` option
Whether or not the delay should be applied only if the user is using touch (eg. on a mobile device). No delay will be applied in any other case. Defaults to `false`.
---
#### `swapThreshold` option
Percentage of the target that the swap zone will take up, as a float between `0` and `1`.
[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#swap-threshold)
Demo: http://sortablejs.github.io/Sortable#thresholds
---
#### `invertSwap` option
Set to `true` to set the swap zone to the sides of the target, for the effect of sorting "in between" items.
[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#forcing-inverted-swap-zone)
Demo: http://sortablejs.github.io/Sortable#thresholds
---
#### `invertedSwapThreshold` option
Percentage of the target that the inverted swap zone will take up, as a float between `0` and `1`. If not given, will default to `swapThreshold`.
[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#dealing-with-swap-glitching)
---
#### `direction` option
Direction that the Sortable should sort in. Can be set to `'vertical'`, `'horizontal'`, or a function, which will be called whenever a target is dragged over. Must return `'vertical'` or `'horizontal'`.
[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#direction)
Example of direction detection for vertical list that includes full column and half column elements:
```js
Sortable.create(el, {
direction: function(evt, target, dragEl) {
if (target !== null && target.className.includes('half-column') && dragEl.className.includes('half-column')) {
return 'horizontal';
}
return 'vertical';
}
});
```
---
#### `touchStartThreshold` option
This option is similar to `fallbackTolerance` option.
When the `delay` option is set, some phones with very sensitive touch displays like the Samsung Galaxy S8 will fire
unwanted touchmove events even when your finger is not moving, resulting in the sort not triggering.
This option sets the minimum pointer movement that must occur before the delayed sorting is cancelled.
Values between 3 to 5 are good.
---
#### `disabled` options
Disables the sortable if set to `true`.
Demo: https://jsbin.com/sewokud/edit?js,output
```js
var sortable = Sortable.create(list);
document.getElementById("switcher").onclick = function () {
var state = sortable.option("disabled"); // get
sortable.option("disabled", !state); // set
};
```
---
#### `handle` option
To make list items draggable, Sortable disables text selection by the user.
That's not always desirable. To allow text selection, define a drag handler,
which is an area of every list element that allows it to be dragged around.
Demo: https://jsbin.com/numakuh/edit?html,js,output
```js
Sortable.create(el, {
handle: ".my-handle"
});
```
```html
<ul>
<li><span class="my-handle">::</span> list item text one
<li><span class="my-handle">::</span> list item text two
</ul>
```
```css
.my-handle {
cursor: move;
cursor: -webkit-grabbing;
}
```
---
#### `filter` option
```js
Sortable.create(list, {
filter: ".js-remove, .js-edit",
onFilter: function (evt) {
var item = evt.item,
ctrl = evt.target;
if (Sortable.utils.is(ctrl, ".js-remove")) { // Click on remove button
item.parentNode.removeChild(item); // remove sortable item
}
else if (Sortable.utils.is(ctrl, ".js-edit")) { // Click on edit link
// ...
}
}
})
```
---
#### `ghostClass` option
Class name for the drop placeholder (default `sortable-ghost`).
Demo: https://jsbin.com/henuyiw/edit?css,js,output
```css
.ghost {
opacity: 0.4;
}
```
```js
Sortable.create(list, {
ghostClass: "ghost"
});
```
---
#### `chosenClass` option
Class name for the chosen item (default `sortable-chosen`).
Demo: https://jsbin.com/hoqufox/edit?css,js,output
```css
.chosen {
color: #fff;
background-color: #c00;
}
```
```js
Sortable.create(list, {
delay: 500,
chosenClass: "chosen"
});
```
---
#### `forceFallback` option
If set to `true`, the Fallback for non HTML5 Browser will be used, even if we are using an HTML5 Browser.
This gives us the possibility to test the behaviour for older Browsers even in newer Browser, or make the Drag 'n Drop feel more consistent between Desktop , Mobile and old Browsers.
On top of that, the Fallback always generates a copy of that DOM Element and appends the class `fallbackClass` defined in the options. This behaviour controls the look of this 'dragged' Element.
Demo: https://jsbin.com/sibiput/edit?html,css,js,output
---
#### `fallbackTolerance` option
Emulates the native drag threshold. Specify in pixels how far the mouse should move before it's considered as a drag.
Useful if the items are also clickable like in a list of links.
When the user clicks inside a sortable element, it's not uncommon for your hand to move a little between the time you press and the time you release.
Dragging only starts if you move the pointer past a certain tolerance, so that you don't accidentally start dragging every time you click.
3 to 5 are probably good values.
---
#### `dragoverBubble` option
If set to `true`, the dragover event will bubble to parent sortables. Works on both fallback and native dragover event.
By default, it is false, but Sortable will only stop bubbling the event once the element has been inserted into a parent Sortable, or *can* be inserted into a parent Sortable, but isn't at that specific time (due to animation, etc).
Since 1.8.0, you will probably want to leave this option as false. Before 1.8.0, it may need to be `true` for nested sortables to work.
---
#### `removeCloneOnHide` option
If set to `false`, the clone is hidden by having it's CSS `display` property set to `none`.
By default, this option is `true`, meaning Sortable will remove the cloned element from the DOM when it is supposed to be hidden.
---
#### `emptyInsertThreshold` option
The distance (in pixels) the mouse must be from an empty sortable while dragging for the drag element to be inserted into that sortable. Defaults to `5`. Set to `0` to disable this feature.
Demo: https://jsbin.com/becavoj/edit?js,output
An alternative to this option would be to set a padding on your list when it is empty.
For example:
```css
ul:empty {
padding-bottom: 20px;
}
```
Warning: For `:empty` to work, it must have no node inside (even text one).
Demo:
https://jsbin.com/yunakeg/edit?html,css,js,output
---
### Event object ([demo](https://jsbin.com/fogujiv/edit?js,output))
- to:`HTMLElement` — list, in which moved element
- from:`HTMLElement` — previous list
- item:`HTMLElement` — dragged element
- clone:`HTMLElement`
- oldIndex:`Number|undefined` — old index within parent
- newIndex:`Number|undefined` — new index within parent
- oldDraggableIndex: `Number|undefined` — old index within parent, only counting draggable elements
- newDraggableIndex: `Number|undefined` — new index within parent, only counting draggable elements
- pullMode:`String|Boolean|undefined` — Pull mode if dragging into another sortable (`"clone"`, `true`, or `false`), otherwise undefined
#### `move` event object
- to:`HTMLElement`
- from:`HTMLElement`
- dragged:`HTMLElement`
- draggedRect:`DOMRect`
- related:`HTMLElement` — element on which have guided
- relatedRect:`DOMRect`
- willInsertAfter:`Boolean``true` if will element be inserted after target (or `false` if before)
---
### Methods
##### option(name:`String`[, value:`*`]):`*`
Get or set the option.
##### closest(el:`HTMLElement`[, selector:`String`]):`HTMLElement|null`
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
##### toArray():`String[]`
Serializes the sortable's item `data-id`'s (`dataIdAttr` option) into an array of string.
##### sort(order:`String[]`, useAnimation:`Boolean`)
Sorts the elements according to the array.
```js
var order = sortable.toArray();
sortable.sort(order.reverse(), true); // apply
```
##### save()
Save the current sorting (see [store](#store))
##### destroy()
Removes the sortable functionality completely.
---
<a name="store"></a>
### Store
Saving and restoring of the sort.
```html
<ul>
<li data-id="1">order</li>
<li data-id="2">save</li>
<li data-id="3">restore</li>
</ul>
```
```js
Sortable.create(el, {
group: "localStorage-example",
store: {
/**
* Get the order of elements. Called once during initialization.
* @param {Sortable} sortable
* @returns {Array}
*/
get: function (sortable) {
var order = localStorage.getItem(sortable.options.group.name);
return order ? order.split('|') : [];
},
/**
* Save the order of elements. Called onEnd (when the item is dropped).
* @param {Sortable} sortable
*/
set: function (sortable) {
var order = sortable.toArray();
localStorage.setItem(sortable.options.group.name, order.join('|'));
}
}
})
```
---
<a name="bs"></a>
### Bootstrap
Demo: https://jsbin.com/visimub/edit?html,js,output
```html
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
<!-- Latest Sortable -->
<script src="http://SortableJS.github.io/Sortable/Sortable.js"></script>
<!-- Simple List -->
<ul id="simpleList" class="list-group">
<li class="list-group-item">This is <a href="http://SortableJS.github.io/Sortable/">Sortable</a></li>
<li class="list-group-item">It works with Bootstrap...</li>
<li class="list-group-item">...out of the box.</li>
<li class="list-group-item">It has support for touch devices.</li>
<li class="list-group-item">Just drag some elements around.</li>
</ul>
<script>
// Simple list
Sortable.create(simpleList, { /* options */ });
</script>
```
---
### Static methods & properties
##### Sortable.create(el:`HTMLElement`[, options:`Object`]):`Sortable`
Create new instance.
---
##### Sortable.active:`Sortable`
The active Sortable instance.
---
##### Sortable.dragged:`HTMLElement`
The element being dragged.
---
##### Sortable.ghost:`HTMLElement`
The ghost element.
---
##### Sortable.clone:`HTMLElement`
The clone element.
---
##### Sortable.get(element:`HTMLElement`):`Sortable`
Get the Sortable instance on an element.
---
##### Sortable.mount(plugin:`...SortablePlugin|SortablePlugin[]`)
Mounts a plugin to Sortable.
---
##### Sortable.utils
* on(el`:HTMLElement`, event`:String`, fn`:Function`) — attach an event handler function
* off(el`:HTMLElement`, event`:String`, fn`:Function`) — remove an event handler
* css(el`:HTMLElement`)`:Object` — get the values of all the CSS properties
* css(el`:HTMLElement`, prop`:String`)`:Mixed` — get the value of style properties
* css(el`:HTMLElement`, prop`:String`, value`:String`) — set one CSS properties
* css(el`:HTMLElement`, props`:Object`) — set more CSS properties
* find(ctx`:HTMLElement`, tagName`:String`[, iterator`:Function`])`:Array` — get elements by tag name
* bind(ctx`:Mixed`, fn`:Function`)`:Function` — Takes a function and returns a new one that will always have a particular context
* is(el`:HTMLElement`, selector`:String`)`:Boolean` — check the current matched set of elements against a selector
* closest(el`:HTMLElement`, selector`:String`[, ctx`:HTMLElement`])`:HTMLElement|Null` — for each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree
* clone(el`:HTMLElement`)`:HTMLElement` — create a deep copy of the set of matched elements
* toggleClass(el`:HTMLElement`, name`:String`, state`:Boolean`) — add or remove one classes from each element
* detectDirection(el`:HTMLElement`)`:String` — automatically detect the [direction](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#direction) of the element as either `'vertical'` or `'horizontal'`
* index(el`:HTMLElement`, selector`:String`)`:Number` — index of the element within its parent for a selected set of elements
* getChild(el`:HTMLElement`, childNum`:Number`, options`:Object`, includeDragEl`:Boolean`):`HTMLElement` — get the draggable element at a given index of draggable elements within a Sortable instance
* expando`:String` — expando property name for internal use, sortableListElement[expando] returns the Sortable instance of that elemenet
---
### Plugins
#### Extra Plugins (included in complete versions)
- [MultiDrag](https://github.com/SortableJS/Sortable/tree/master/plugins/MultiDrag)
- [Swap](https://github.com/SortableJS/Sortable/tree/master/plugins/Swap)
#### Default Plugins (included in default versions)
- [AutoScroll](https://github.com/SortableJS/Sortable/tree/master/plugins/AutoScroll)
- [OnSpill](https://github.com/SortableJS/Sortable/tree/master/plugins/OnSpill)
---
<a name="cdn"></a>
### CDN
```html
<!-- jsDelivr :: Sortable :: Latest (https://www.jsdelivr.com/package/npm/sortablejs) -->
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
```
---
### Contributing (Issue/PR)
Please, [read this](CONTRIBUTING.md).
---
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/SortableJS/Sortable/graphs/contributors"><img src="https://opencollective.com/Sortable/contributors.svg?width=890&button=false" /></a>
### Financial Contributors
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/Sortable/contribute)]
#### Individuals
<a href="https://opencollective.com/Sortable"><img src="https://opencollective.com/Sortable/individuals.svg?width=890"></a>
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/Sortable/contribute)]
<a href="https://opencollective.com/Sortable/organization/0/website"><img src="https://opencollective.com/Sortable/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/1/website"><img src="https://opencollective.com/Sortable/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/2/website"><img src="https://opencollective.com/Sortable/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/3/website"><img src="https://opencollective.com/Sortable/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/4/website"><img src="https://opencollective.com/Sortable/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/5/website"><img src="https://opencollective.com/Sortable/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/6/website"><img src="https://opencollective.com/Sortable/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/7/website"><img src="https://opencollective.com/Sortable/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/8/website"><img src="https://opencollective.com/Sortable/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/Sortable/organization/9/website"><img src="https://opencollective.com/Sortable/organization/9/avatar.svg"></a>
## MIT LICENSE
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.

3373
www/bower_components/Sortable/Sortable.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
module.exports = function(api) {
api.cache(true);
let presets;
if (process.env.NODE_ENV === 'es') {
presets = [
[
"@babel/preset-env",
{
"modules": false
}
]
];
} else if (process.env.NODE_ENV === 'umd') {
presets = [
[
"@babel/preset-env"
]
];
}
return {
plugins: ['@babel/plugin-transform-object-assign'],
presets
};
};

View File

@@ -0,0 +1,30 @@
{
"name": "Sortable",
"main": [
"Sortable.js"
],
"homepage": "http://SortableJS.github.io/Sortable/",
"authors": [
"RubaXa <ibnRubaXa@gmail.com>",
"owenm <owen23355@gmail.com>"
],
"description": "JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery required. Supports Meteor, AngularJS, React, Polymer, Vue, Knockout and any CSS library, e.g. Bootstrap.",
"keywords": [
"sortable",
"reorder",
"list",
"html5",
"drag",
"and",
"drop",
"dnd",
"web-components"
],
"license": "MIT",
"ignore": [
"node_modules",
"bower_components",
"test",
"tests"
]
}

View File

@@ -0,0 +1,8 @@
import Sortable from './entry-defaults.js';
import Swap from '../plugins/Swap';
import MultiDrag from '../plugins/MultiDrag';
Sortable.mount(new Swap());
Sortable.mount(new MultiDrag());
export default Sortable;

View File

@@ -0,0 +1,19 @@
import Sortable from '../src/Sortable.js';
import AutoScroll from '../plugins/AutoScroll';
import OnSpill from '../plugins/OnSpill';
import Swap from '../plugins/Swap';
import MultiDrag from '../plugins/MultiDrag';
export default Sortable;
export {
Sortable,
// Default
AutoScroll,
OnSpill,
// Extra
Swap,
MultiDrag
};

View File

@@ -0,0 +1,19 @@
import Sortable from '../src/Sortable.js';
import AutoScroll from '../plugins/AutoScroll';
import { RemoveOnSpill, RevertOnSpill } from '../plugins/OnSpill';
// Extra
import Swap from '../plugins/Swap';
import MultiDrag from '../plugins/MultiDrag';
Sortable.mount(new AutoScroll());
Sortable.mount(RemoveOnSpill, RevertOnSpill);
export default Sortable;
export {
Sortable,
// Extra
Swap,
MultiDrag
};

460
www/bower_components/Sortable/index.html vendored Normal file
View File

@@ -0,0 +1,460 @@
<!DOCTYPE html>
<html>
<head>
<link rel="icon" type="image/png" href="st/og-image.png">
<title>SortableJS</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="st/theme.css">
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta property="og:image" content="/st/og-image.png"/>
<meta name="keywords" content="sortable, reorder, list, javascript, html5, drag and drop, dnd, animation, groups, dnd, sortableJS"/>
<meta name="description" content="Sortable — is a JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery required. Supports Meteor, AngularJS, React, Polymer, Vue, Knockout and any CSS library, e.g. Bootstrap."/>
<meta name="viewport" content="width=device-width, initial-scale=0.5"/>
</head>
<body>
<a href="https://github.com/SortableJS/Sortable"><img style="position: fixed; top: 0; right: 0; border: 0; z-index:99999" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
<div class="container">
<div class="text-center row header">
<img class="mx-auto d-block" src="st/og-image.png" style="max-width: 200px; max-height: 200px" />
<h1 class="col-12">SortableJS</h1>
<h3 class="col-12 text-center">JavaScript library for reorderable drag-and-drop lists</h3>
<div class="toc col-12 col-md-5 mt-3">
<h5>Features</h5>
<li><a href="#simple-list">Simple list</a></li>
<li><a href="#shared-lists">Shared lists</a></li>
<li><a href="#cloning">Cloning</a></li>
<li><a href="#sorting-disabled">Disabling sorting</a></li>
<li><a href="#handle">Handles</a></li>
<li><a href="#filter">Filter</a></li>
<li><a href="#thresholds">Thresholds</a></li>
<h5>Examples</h5>
<li><a href="#grid">Grid</a></li>
<li><a href="#nested">Nested sortables</a></li>
<h5>Plugins</h5>
<li><a href="#multi-drag">MultiDrag</a></li>
<li><a href="#swap">Swap</a></li>
<h5><a href="#comparisons">Comparisons</a></h5>
<h5><a href="#frameworks">Framework Support</a></h5>
</div>
</div>
<div class="row">
<h2 class="col-12">Features</h2>
</div>
<hr />
<div id="simple-list" class="row">
<h4 class="col-12">Simple list example</h4>
<div id="example1" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example1, {
animation: 150,
ghostClass: 'blue-background-class'
});</pre>
</div>
</div>
<hr />
<div id="shared-lists" class="row">
<h4 class="col-12">Shared lists</h4>
<div id="example2-left" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div id="example2-right" class="list-group col">
<div class="list-group-item tinted">Item 1</div>
<div class="list-group-item tinted">Item 2</div>
<div class="list-group-item tinted">Item 3</div>
<div class="list-group-item tinted">Item 4</div>
<div class="list-group-item tinted">Item 5</div>
<div class="list-group-item tinted">Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example2Left, {
group: 'shared', // set both lists to same group
animation: 150
});
new Sortable(example2Right, {
group: 'shared',
animation: 150
});</pre>
</div>
</div>
<hr />
<div id="cloning" class="row">
<h4 class="col-12">Cloning</h4>
<p class="col-12">Try dragging from one list to another. The item you drag will be cloned and the clone will stay in the original list.</p>
<div id="example3-left" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div id="example3-right" class="list-group col">
<div class="list-group-item tinted">Item 1</div>
<div class="list-group-item tinted">Item 2</div>
<div class="list-group-item tinted">Item 3</div>
<div class="list-group-item tinted">Item 4</div>
<div class="list-group-item tinted">Item 5</div>
<div class="list-group-item tinted">Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example3Left, {
group: {
name: 'shared',
pull: 'clone' // To clone: set pull to 'clone'
},
animation: 150
});
new Sortable(example3Right, {
group: {
name: 'shared',
pull: 'clone'
},
animation: 150
});</pre>
</div>
</div>
<hr />
<div id="sorting-disabled" class="row">
<h4 class="col-12">Disabling Sorting</h4>
<p class="col-12">Try sorting the list on the left. It is not possible because it has it's <code>sort</code> option set to false. However, you can still drag from the list on the left to the list on the right.</p>
<div id="example4-left" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div id="example4-right" class="list-group col">
<div class="list-group-item tinted">Item 1</div>
<div class="list-group-item tinted">Item 2</div>
<div class="list-group-item tinted">Item 3</div>
<div class="list-group-item tinted">Item 4</div>
<div class="list-group-item tinted">Item 5</div>
<div class="list-group-item tinted">Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example4Left, {
group: {
name: 'shared',
pull: 'clone',
put: false // Do not allow items to be put into this list
},
animation: 150,
sort: false // To disable sorting: set sort to false
});
new Sortable(example4Right, {
group: 'shared',
animation: 150
});</pre>
</div>
</div>
<hr />
<div id="handle" class="row">
<h4 class="col-12">Handle</h4>
<div id="example5" class="list-group col">
<div class="list-group-item"><i class="fas fa-arrows-alt handle"></i>&nbsp;&nbsp;Item 1</div>
<div class="list-group-item"><i class="fas fa-arrows-alt handle"></i>&nbsp;&nbsp;Item 2</div>
<div class="list-group-item"><i class="fas fa-arrows-alt handle"></i>&nbsp;&nbsp;Item 3</div>
<div class="list-group-item"><i class="fas fa-arrows-alt handle"></i>&nbsp;&nbsp;Item 4</div>
<div class="list-group-item"><i class="fas fa-arrows-alt handle"></i>&nbsp;&nbsp;Item 5</div>
<div class="list-group-item"><i class="fas fa-arrows-alt handle"></i>&nbsp;&nbsp;Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example5, {
handle: '.handle', // handle's class
animation: 150
});</pre>
</div>
</div>
<hr />
<div id="filter" class="row">
<h4 class="col-12">Filter</h4>
<p class="col-12">Try dragging the item with a red background. It cannot be done, because that item is filtered out using the <code>filter</code> option.</p>
<div id="example6" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item bg-danger filtered">Filtered</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example6, {
filter: '.filtered', // 'filtered' class is not draggable
animation: 150
});</pre>
</div>
</div>
<hr />
<div id="thresholds" class="row">
<h4 class="col-12">Thresholds</h4>
<p class="col-12">Try modifying the inputs below to affect the swap thresholds. You can see the swap zones of the squares colored in dark blue, while the "dead zones" (that do not cause a swap) are colored in light blue.</p>
<div id="example7" class="square-section col">
<div class="square">
<div style="display: none;" class="inverted-swap-threshold-indicator indicator-left"></div>
<div class="swap-threshold-indicator"></div>
<div style="display: none;" class="inverted-swap-threshold-indicator indicator-right"></div>
<div class="num-indicator">1</div>
</div><!--
--><div class="square">
<div style="display: none;" class="inverted-swap-threshold-indicator indicator-left"></div>
<div class="swap-threshold-indicator"></div>
<div style="display: none;" class="inverted-swap-threshold-indicator indicator-right"></div>
<div class="num-indicator">2</div>
</div>
</div>
<div class="col-12 input-section">
<form>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="example7SwapThresholdInput">Swap Threshold</label>
<div class="col-sm-8 col-form-label">
<input min="0" max="1" value="1" step="0.01" type="range" class="form-control-range" id="example7SwapThresholdInput">
</div>
</div>
<div class="form-group row">
<div class="col-sm-2">Invert Swap</div>
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="example7InvertSwapInput">
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="example7DirectionInput">Direction</label>
<select class="col-sm-4 form-control" id="example7DirectionInput">
<option value="h" selected>Horizontal</option>
<option value="v">Vertical</option>
</select>
</div>
</form>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(example7, {
swapThreshold: <span id="example7SwapThresholdCode">1</span>,<span id="example7InvertSwapCode" style="display: none">
invertSwap: true,</span>
animation: 150
});</pre>
</div>
</div>
<div class="row">
<h2 class="col-12">Examples</h2>
</div>
<hr />
<div id="grid" class="row">
<h4 class="col-12">Grid Example</h4>
<div id="gridDemo" class="col">
<div class="grid-square">Item 1</div><!--
--><div class="grid-square">Item 2</div><!--
--><div class="grid-square">Item 3</div><!--
--><div class="grid-square">Item 4</div><!--
--><div class="grid-square">Item 5</div><!--
--><div class="grid-square">Item 6</div><!--
--><div class="grid-square">Item 7</div><!--
--><div class="grid-square">Item 8</div><!--
--><div class="grid-square">Item 9</div><!--
--><div class="grid-square">Item 10</div><!--
--><div class="grid-square">Item 11</div><!--
--><div class="grid-square">Item 12</div><!--
--><div class="grid-square">Item 13</div><!--
--><div class="grid-square">Item 14</div><!--
--><div class="grid-square">Item 15</div><!--
--><div class="grid-square">Item 16</div><!--
--><div class="grid-square">Item 17</div><!--
--><div class="grid-square">Item 18</div><!--
--><div class="grid-square">Item 19</div><!--
--><div class="grid-square">Item 20</div>
</div>
</div>
<hr />
<div id="nested" class="row">
<h4 class="col-12">Nested Sortables Example</h4>
<p class="col-12">NOTE: When using nested Sortables with animation, it is recommended that the <code>fallbackOnBody</code> option is set to true. <br />It is also always recommended that either the <code>invertSwap</code> option is set to true, or the <code>swapThreshold</code> option is lower than the default value of 1 (eg <code>0.65</code>).</p>
<div id="nestedDemo" class="list-group col nested-sortable">
<div class="list-group-item nested-1">Item 1.1
<div class="list-group nested-sortable">
<div class="list-group-item nested-2">Item 2.1</div>
<div class="list-group-item nested-2">Item 2.2
<div class="list-group nested-sortable">
<div class="list-group-item nested-3">Item 3.1</div>
<div class="list-group-item nested-3">Item 3.2</div>
<div class="list-group-item nested-3">Item 3.3</div>
<div class="list-group-item nested-3">Item 3.4</div>
</div>
</div>
<div class="list-group-item nested-2">Item 2.3</div>
<div class="list-group-item nested-2">Item 2.4</div>
</div>
</div>
<div class="list-group-item nested-1">Item 1.2</div>
<div class="list-group-item nested-1">Item 1.3</div>
<div class="list-group-item nested-1">Item 1.4
<div class="list-group nested-sortable">
<div class="list-group-item nested-2">Item 2.1</div>
<div class="list-group-item nested-2">Item 2.2</div>
<div class="list-group-item nested-2">Item 2.3</div>
<div class="list-group-item nested-2">Item 2.4</div>
</div>
</div>
<div class="list-group-item nested-1">Item 1.5</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">// Loop through each nested sortable element
for (var i = 0; i < nestedSortables.length; i++) {
new Sortable(nestedSortables[i], {
group: 'nested',
animation: 150,
fallbackOnBody: true,
swapThreshold: 0.65
});
}</pre>
</div>
</div>
<div class="row">
<h2 class="col-12">Plugins</h2>
</div>
<hr />
<div id="multi-drag" class="row">
<h4 class="col-12">MultiDrag</h4>
<p class="col-12">The <a target="_blank" href="https://github.com/SortableJS/Sortable/tree/master/plugins/MultiDrag">MultiDrag</a> plugin allows for multiple items to be dragged at a time. You can click to "select" multiple items, and then drag them as one item.</p>
<div id="multiDragDemo" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(multiDragDemo, {
multiDrag: true,
selectedClass: 'selected',
fallbackTolerance: 3, // So that we can select items on mobile
animation: 150
});</pre>
</div>
</div>
<hr />
<div id="swap" class="row">
<h4 class="col-12">Swap</h4>
<p class="col-12">The <a target="_blank" href="https://github.com/SortableJS/Sortable/tree/master/plugins/Swap">Swap</a> plugin changes the behaviour of Sortable to allow for items to be swapped with eachother rather than sorted.</p>
<div id="swapDemo" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div style="padding: 0" class="col-12">
<pre class="prettyprint">new Sortable(swapDemo, {
swap: true, // Enable swap plugin
swapClass: 'highlight', // The class applied to the hovered swap item
animation: 150
});</pre>
</div>
</div>
<hr />
<div class="mt-4"></div>
<div id="comparisons" class="row">
<h2 class="col-12">Comparisons</h2>
</div>
<hr />
<div class="row frameworks">
<h2 class="col-12 text-center">jQuery-UI</h2>
<iframe class="mx-auto" src="https://player.vimeo.com/video/311581236?title=0&byline=0&portrait=0" width="640" height="361" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<h2 class="col-12 text-center mt-5">Dragula</h2>
<iframe class="mx-auto" src="https://player.vimeo.com/video/311584137?title=0&byline=0&portrait=0" width="640" height="361" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<div class="mt-4"></div>
<div id="frameworks" class="row">
<h2 class="col-12">Framework Support</h2>
</div>
<hr />
<div class="row frameworks">
<h3 class="col-6">Vue</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/Vue.Draggable">Vue.Draggable</a></h3>
<h3 class="col-6">React</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/react-sortablejs">react-sortablejs</a></h3>
<h3 class="col-6">Angular</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/ngx-sortablejs">ngx-sortablejs</a></h3>
<h3 class="col-6">jQuery</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/jquery-sortablejs">jquery-sortablejs</a></h3>
<h3 class="col-6">Knockout</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/knockout-sortablejs">knockout-sortablejs</a></h3>
<h3 class="col-6">Meteor</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/meteor-sortablejs">meteor-sortablejs</a></h3>
<h3 class="col-6">Polymer</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/polymer-sortablejs">polymer-sortablejs</a></h3>
<h3 class="col-6">Ember</h3>
<h3 class="col-6"><a target="_blank" href="https://github.com/SortableJS/ember-sortablejs">ember-sortablejs</a></h3>
</div>
</div>
<!-- Latest Sortable -->
<script src="./Sortable.js"></script>
<script type="text/javascript" src="st/prettify/prettify.js"></script>
<script type="text/javascript" src="st/prettify/run_prettify.js"></script>
<script src="st/app.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

12211
www/bower_components/Sortable/package-lock.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
{
"name": "sortablejs",
"exportName": "Sortable",
"version": "1.15.7",
"devDependencies": {
"@babel/core": "^7.4.4",
"@babel/plugin-transform-object-assign": "^7.2.0",
"@babel/preset-env": "^7.4.4",
"rollup": "^1.11.3",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.0.0",
"testcafe": "^1.3.1",
"testcafe-browser-provider-saucelabs": "^1.7.0",
"testcafe-reporter-xunit": "^2.1.0",
"uglify-js": "^3.5.12"
},
"description": "JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery required. Supports Meteor, AngularJS, React, Polymer, Vue, Knockout and any CSS library, e.g. Bootstrap.",
"main": "./Sortable.min.js",
"module": "modular/sortable.esm.js",
"scripts": {
"build:umd": "set NODE_ENV=umd&& rollup -c ./scripts/umd-build.js",
"build:umd:watch": "set NODE_ENV=umd&& rollup -w -c ./scripts/umd-build.js",
"build:es": "set NODE_ENV=es&& rollup -c ./scripts/esm-build.js",
"build:es:watch": "set NODE_ENV=es&& rollup -w -c ./scripts/esm-build.js",
"minify": "node ./scripts/minify.js",
"build": "npm run build:es && npm run build:umd && npm run minify",
"test:compat": "node ./scripts/test-compat.js",
"test": "node ./scripts/test.js"
},
"maintainers": [
"Konstantin Lebedev <ibnRubaXa@gmail.com>",
"Owen Mills <owen23355@gmail.com>"
],
"repository": {
"type": "git",
"url": "git://github.com/SortableJS/Sortable.git"
},
"files": [
"Sortable.js",
"Sortable.min.js",
"modular/",
"src/"
],
"keywords": [
"sortable",
"reorder",
"drag",
"meteor",
"angular",
"ng-sortable",
"react",
"vue",
"mixin"
],
"license": "MIT"
}

View File

@@ -0,0 +1,271 @@
import {
on,
off,
css,
throttle,
cancelThrottle,
scrollBy,
getParentAutoScrollElement,
expando,
getRect,
getWindowScrollingElement
} from '../../src/utils.js';
import Sortable from '../../src/Sortable.js';
import { Edge, IE11OrLess, Safari } from '../../src/BrowserInfo.js';
let autoScrolls = [],
scrollEl,
scrollRootEl,
scrolling = false,
lastAutoScrollX,
lastAutoScrollY,
touchEvt,
pointerElemChangedInterval;
function AutoScrollPlugin() {
function AutoScroll() {
this.defaults = {
scroll: true,
forceAutoScrollFallback: false,
scrollSensitivity: 30,
scrollSpeed: 10,
bubbleScroll: true
};
// Bind all private methods
for (let fn in this) {
if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
this[fn] = this[fn].bind(this);
}
}
}
AutoScroll.prototype = {
dragStarted({ originalEvent }) {
if (this.sortable.nativeDraggable) {
on(document, 'dragover', this._handleAutoScroll);
} else {
if (this.options.supportPointer) {
on(document, 'pointermove', this._handleFallbackAutoScroll);
} else if (originalEvent.touches) {
on(document, 'touchmove', this._handleFallbackAutoScroll);
} else {
on(document, 'mousemove', this._handleFallbackAutoScroll);
}
}
},
dragOverCompleted({ originalEvent }) {
// For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)
if (!this.options.dragOverBubble && !originalEvent.rootEl) {
this._handleAutoScroll(originalEvent);
}
},
drop() {
if (this.sortable.nativeDraggable) {
off(document, 'dragover', this._handleAutoScroll);
} else {
off(document, 'pointermove', this._handleFallbackAutoScroll);
off(document, 'touchmove', this._handleFallbackAutoScroll);
off(document, 'mousemove', this._handleFallbackAutoScroll);
}
clearPointerElemChangedInterval();
clearAutoScrolls();
cancelThrottle();
},
nulling() {
touchEvt =
scrollRootEl =
scrollEl =
scrolling =
pointerElemChangedInterval =
lastAutoScrollX =
lastAutoScrollY = null;
autoScrolls.length = 0;
},
_handleFallbackAutoScroll(evt) {
this._handleAutoScroll(evt, true);
},
_handleAutoScroll(evt, fallback) {
const x = (evt.touches ? evt.touches[0] : evt).clientX,
y = (evt.touches ? evt.touches[0] : evt).clientY,
elem = document.elementFromPoint(x, y);
touchEvt = evt;
// IE does not seem to have native autoscroll,
// Edge's autoscroll seems too conditional,
// MACOS Safari does not have autoscroll,
// Firefox and Chrome are good
if (fallback || this.options.forceAutoScrollFallback || Edge || IE11OrLess || Safari) {
autoScroll(evt, this.options, elem, fallback);
// Listener for pointer element change
let ogElemScroller = getParentAutoScrollElement(elem, true);
if (
scrolling &&
(
!pointerElemChangedInterval ||
x !== lastAutoScrollX ||
y !== lastAutoScrollY
)
) {
pointerElemChangedInterval && clearPointerElemChangedInterval();
// Detect for pointer elem change, emulating native DnD behaviour
pointerElemChangedInterval = setInterval(() => {
let newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true);
if (newElem !== ogElemScroller) {
ogElemScroller = newElem;
clearAutoScrolls();
}
autoScroll(evt, this.options, newElem, fallback);
}, 10);
lastAutoScrollX = x;
lastAutoScrollY = y;
}
} else {
// if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
clearAutoScrolls();
return;
}
autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);
}
}
};
return Object.assign(AutoScroll, {
pluginName: 'scroll',
initializeByDefault: true
});
}
function clearAutoScrolls() {
autoScrolls.forEach(function(autoScroll) {
clearInterval(autoScroll.pid);
});
autoScrolls = [];
}
function clearPointerElemChangedInterval() {
clearInterval(pointerElemChangedInterval);
}
const autoScroll = throttle(function(evt, options, rootEl, isFallback) {
// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
if (!options.scroll) return;
const x = (evt.touches ? evt.touches[0] : evt).clientX,
y = (evt.touches ? evt.touches[0] : evt).clientY,
sens = options.scrollSensitivity,
speed = options.scrollSpeed,
winScroller = getWindowScrollingElement();
let scrollThisInstance = false,
scrollCustomFn;
// New scroll root, set scrollEl
if (scrollRootEl !== rootEl) {
scrollRootEl = rootEl;
clearAutoScrolls();
scrollEl = options.scroll;
scrollCustomFn = options.scrollFn;
if (scrollEl === true) {
scrollEl = getParentAutoScrollElement(rootEl, true);
}
}
let layersOut = 0;
let currentParent = scrollEl;
do {
let el = currentParent,
rect = getRect(el),
top = rect.top,
bottom = rect.bottom,
left = rect.left,
right = rect.right,
width = rect.width,
height = rect.height,
canScrollX,
canScrollY,
scrollWidth = el.scrollWidth,
scrollHeight = el.scrollHeight,
elCSS = css(el),
scrollPosX = el.scrollLeft,
scrollPosY = el.scrollTop;
if (el === winScroller) {
canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible');
canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible');
} else {
canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll');
canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll');
}
let vx = canScrollX && (Math.abs(right - x) <= sens && (scrollPosX + width) < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX);
let vy = canScrollY && (Math.abs(bottom - y) <= sens && (scrollPosY + height) < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY);
if (!autoScrolls[layersOut]) {
for (let i = 0; i <= layersOut; i++) {
if (!autoScrolls[i]) {
autoScrolls[i] = {};
}
}
}
if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) {
autoScrolls[layersOut].el = el;
autoScrolls[layersOut].vx = vx;
autoScrolls[layersOut].vy = vy;
clearInterval(autoScrolls[layersOut].pid);
if (vx != 0 || vy != 0) {
scrollThisInstance = true;
/* jshint loopfunc:true */
autoScrolls[layersOut].pid = setInterval((function () {
// emulate drag over during autoscroll (fallback), emulating native DnD behaviour
if (isFallback && this.layer === 0) {
Sortable.active._onTouchMove(touchEvt); // To move ghost if it is positioned absolutely
}
let scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
let scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
if (typeof(scrollCustomFn) === 'function') {
if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt, autoScrolls[this.layer].el) !== 'continue') {
return;
}
}
scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
}).bind({layer: layersOut}), 24);
}
}
layersOut++;
} while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not
}, 30);
export default AutoScrollPlugin;

View File

@@ -0,0 +1,110 @@
## AutoScroll
This plugin allows for the page to automatically scroll during dragging near a scrollable element's edge on mobile devices and IE9 (or whenever fallback is enabled), and also enhances most browser's native drag-and-drop autoscrolling.
Demo:
- `window`: https://jsbin.com/dosilir/edit?js,output
- `overflow: hidden`: https://jsbin.com/xecihez/edit?html,js,output
**This plugin is a default plugin, and is included in the default UMD and ESM builds of Sortable**
---
### Mounting
```js
import { Sortable, AutoScroll } from 'sortablejs';
Sortable.mount(new AutoScroll());
```
---
### Options
```js
new Sortable(el, {
scroll: true, // Enable the plugin. Can be HTMLElement.
forceAutoScrollFallback: false, // force autoscroll plugin to enable even when native browser autoscroll is available
scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... }, // if you have custom scrollbar scrollFn may be used for autoscrolling
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px, speed of the scrolling
bubbleScroll: true // apply autoscroll to all parent elements, allowing for easier movement
});
```
---
#### `scroll` option
Enables the plugin. Defaults to `true`. May also be set to an HTMLElement which will be where autoscrolling is rooted.
**Note: Just because this plugin is enabled does not mean that it will always be used for autoscrolling. Some browsers have native drag and drop autoscroll, in which case this autoscroll plugin won't be invoked. If you wish to have this always be invoked for autoscrolling, set the option `forceAutoScrollFallback` to `true`.**
Demo:
- `window`: https://jsbin.com/dosilir/edit?js,output
- `overflow: hidden`: https://jsbin.com/xecihez/edit?html,js,output
---
#### `forceAutoScrollFallback` option
Enables sortable's autoscroll even when the browser can handle it (with native drag and drop). Defaults to `false`. This will not disable the native autoscrolling. Note that setting `forceFallback: true` in the sortable options will also enable this.
---
#### `scrollFn` option
Useful when you have custom scrollbar with dedicated scroll function.
Defines a function that will be used for autoscrolling. Sortable uses el.scrollTop/el.scrollLeft by default. Set this option if you wish to handle it differently.
This function should return `'continue'` if it wishes to allow Sortable's native autoscrolling, otherwise Sortable will not scroll anything if this option is set.
**Note that this option will only work if Sortable's autoscroll function is invoked.**
It is invoked if any of the following are true:
- The `forceFallback: true` option is set
- It is a mobile device
- The browser is either Safari, Internet Explorer, or Edge
---
#### `scrollSensitivity` option
Defines how near the mouse must be to an edge to start scrolling.
**Note that this option will only work if Sortable's autoscroll function is invoked.**
It is invoked if any of the following are true:
- The `forceFallback: true` option is set
- It is a mobile device
- The browser is either Safari, Internet Explorer, or Edge
---
#### `scrollSpeed` option
The speed at which the window should scroll once the mouse pointer gets within the `scrollSensitivity` distance.
**Note that this option will only work if Sortable's autoscroll function is invoked.**
It is invoked if any of the following are true:
- The `forceFallback: true` option is set
- It is a mobile device
- The browser is either Safari, Internet Explorer, or Edge
---
#### `bubbleScroll` option
If set to `true`, the normal `autoscroll` function will also be applied to all parent elements of the element the user is dragging over.
Demo: https://jsbin.com/kesewor/edit?html,js,output
---

View File

@@ -0,0 +1 @@
export { default } from './AutoScroll.js';

View File

@@ -0,0 +1,633 @@
import {
toggleClass,
getRect,
index,
closest,
on,
off,
clone,
css,
setRect,
unsetRect,
matrix,
expando
} from '../../src/utils.js';
import dispatchEvent from '../../src/EventDispatcher.js';
let multiDragElements = [],
multiDragClones = [],
lastMultiDragSelect, // for selection with modifier key down (SHIFT)
multiDragSortable,
initialFolding = false, // Initial multi-drag fold when drag started
folding = false, // Folding any other time
dragStarted = false,
dragEl,
clonesFromRect,
clonesHidden;
function MultiDragPlugin() {
function MultiDrag(sortable) {
// Bind all private methods
for (let fn in this) {
if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
this[fn] = this[fn].bind(this);
}
}
if (!sortable.options.avoidImplicitDeselect) {
if (sortable.options.supportPointer) {
on(document, 'pointerup', this._deselectMultiDrag);
} else {
on(document, 'mouseup', this._deselectMultiDrag);
on(document, 'touchend', this._deselectMultiDrag);
}
}
on(document, 'keydown', this._checkKeyDown);
on(document, 'keyup', this._checkKeyUp);
this.defaults = {
selectedClass: 'sortable-selected',
multiDragKey: null,
avoidImplicitDeselect: false,
setData(dataTransfer, dragEl) {
let data = '';
if (multiDragElements.length && multiDragSortable === sortable) {
multiDragElements.forEach((multiDragElement, i) => {
data += (!i ? '' : ', ') + multiDragElement.textContent;
});
} else {
data = dragEl.textContent;
}
dataTransfer.setData('Text', data);
}
};
}
MultiDrag.prototype = {
multiDragKeyDown: false,
isMultiDrag: false,
delayStartGlobal({ dragEl: dragged }) {
dragEl = dragged;
},
delayEnded() {
this.isMultiDrag = ~multiDragElements.indexOf(dragEl);
},
setupClone({ sortable, cancel }) {
if (!this.isMultiDrag) return;
for (let i = 0; i < multiDragElements.length; i++) {
multiDragClones.push(clone(multiDragElements[i]));
multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex;
multiDragClones[i].draggable = false;
multiDragClones[i].style['will-change'] = '';
toggleClass(multiDragClones[i], this.options.selectedClass, false);
multiDragElements[i] === dragEl && toggleClass(multiDragClones[i], this.options.chosenClass, false);
}
sortable._hideClone();
cancel();
},
clone({ sortable, rootEl, dispatchSortableEvent, cancel }) {
if (!this.isMultiDrag) return;
if (!this.options.removeCloneOnHide) {
if (multiDragElements.length && multiDragSortable === sortable) {
insertMultiDragClones(true, rootEl);
dispatchSortableEvent('clone');
cancel();
}
}
},
showClone({ cloneNowShown, rootEl, cancel }) {
if (!this.isMultiDrag) return;
insertMultiDragClones(false, rootEl);
multiDragClones.forEach(clone => {
css(clone, 'display', '');
});
cloneNowShown();
clonesHidden = false;
cancel();
},
hideClone({ sortable, cloneNowHidden, cancel }) {
if (!this.isMultiDrag) return;
multiDragClones.forEach(clone => {
css(clone, 'display', 'none');
if (this.options.removeCloneOnHide && clone.parentNode) {
clone.parentNode.removeChild(clone);
}
});
cloneNowHidden();
clonesHidden = true;
cancel();
},
dragStartGlobal({ sortable }) {
if (!this.isMultiDrag && multiDragSortable) {
multiDragSortable.multiDrag._deselectMultiDrag();
}
multiDragElements.forEach(multiDragElement => {
multiDragElement.sortableIndex = index(multiDragElement);
});
// Sort multi-drag elements
multiDragElements = multiDragElements.sort(function(a, b) {
return a.sortableIndex - b.sortableIndex;
});
dragStarted = true;
},
dragStarted({ sortable }) {
if (!this.isMultiDrag) return;
if (this.options.sort) {
// Capture rects,
// hide multi drag elements (by positioning them absolute),
// set multi drag elements rects to dragRect,
// show multi drag elements,
// animate to rects,
// unset rects & remove from DOM
sortable.captureAnimationState();
if (this.options.animation) {
multiDragElements.forEach(multiDragElement => {
if (multiDragElement === dragEl) return;
css(multiDragElement, 'position', 'absolute');
});
let dragRect = getRect(dragEl, false, true, true);
multiDragElements.forEach(multiDragElement => {
if (multiDragElement === dragEl) return;
setRect(multiDragElement, dragRect);
});
folding = true;
initialFolding = true;
}
}
sortable.animateAll(() => {
folding = false;
initialFolding = false;
if (this.options.animation) {
multiDragElements.forEach(multiDragElement => {
unsetRect(multiDragElement);
});
}
// Remove all auxiliary multidrag items from el, if sorting enabled
if (this.options.sort) {
removeMultiDragElements();
}
});
},
dragOver({ target, completed, cancel }) {
if (folding && ~multiDragElements.indexOf(target)) {
completed(false);
cancel();
}
},
revert({ fromSortable, rootEl, sortable, dragRect }) {
if (multiDragElements.length > 1) {
// Setup unfold animation
multiDragElements.forEach(multiDragElement => {
sortable.addAnimationState({
target: multiDragElement,
rect: folding ? getRect(multiDragElement) : dragRect
});
unsetRect(multiDragElement);
multiDragElement.fromRect = dragRect;
fromSortable.removeAnimationState(multiDragElement);
});
folding = false;
insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
}
},
dragOverCompleted({ sortable, isOwner, insertion, activeSortable, parentEl, putSortable }) {
let options = this.options;
if (insertion) {
// Clones must be hidden before folding animation to capture dragRectAbsolute properly
if (isOwner) {
activeSortable._hideClone();
}
initialFolding = false;
// If leaving sort:false root, or already folding - Fold to new location
if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
// Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible
let dragRectAbsolute = getRect(dragEl, false, true, true);
multiDragElements.forEach(multiDragElement => {
if (multiDragElement === dragEl) return;
setRect(multiDragElement, dragRectAbsolute);
// Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted
// while folding, and so that we can capture them again because old sortable will no longer be fromSortable
parentEl.appendChild(multiDragElement);
});
folding = true;
}
// Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out
if (!isOwner) {
// Only remove if not folding (folding will remove them anyways)
if (!folding) {
removeMultiDragElements();
}
if (multiDragElements.length > 1) {
let clonesHiddenBefore = clonesHidden;
activeSortable._showClone(sortable);
// Unfold animation for clones if showing from hidden
if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) {
multiDragClones.forEach(clone => {
activeSortable.addAnimationState({
target: clone,
rect: clonesFromRect
});
clone.fromRect = clonesFromRect;
clone.thisAnimationDuration = null;
});
}
} else {
activeSortable._showClone(sortable);
}
}
}
},
dragOverAnimationCapture({ dragRect, isOwner, activeSortable }) {
multiDragElements.forEach(multiDragElement => {
multiDragElement.thisAnimationDuration = null;
});
if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) {
clonesFromRect = Object.assign({}, dragRect);
let dragMatrix = matrix(dragEl, true);
clonesFromRect.top -= dragMatrix.f;
clonesFromRect.left -= dragMatrix.e;
}
},
dragOverAnimationComplete() {
if (folding) {
folding = false;
removeMultiDragElements();
}
},
drop({ originalEvent: evt, rootEl, parentEl, sortable, dispatchSortableEvent, oldIndex, putSortable }) {
let toSortable = (putSortable || this.sortable);
if (!evt) return;
let options = this.options,
children = parentEl.children;
// Multi-drag selection
if (!dragStarted) {
if (options.multiDragKey && !this.multiDragKeyDown) {
this._deselectMultiDrag();
}
toggleClass(dragEl, options.selectedClass, !~multiDragElements.indexOf(dragEl));
if (!~multiDragElements.indexOf(dragEl)) {
multiDragElements.push(dragEl);
dispatchEvent({
sortable,
rootEl,
name: 'select',
targetEl: dragEl,
originalEvent: evt
});
// Modifier activated, select from last to dragEl
if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) {
let lastIndex = index(lastMultiDragSelect),
currentIndex = index(dragEl);
if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) {
// Must include lastMultiDragSelect (select it), in case modified selection from no selection
// (but previous selection existed)
let n, i;
if (currentIndex > lastIndex) {
i = lastIndex;
n = currentIndex;
} else {
i = currentIndex;
n = lastIndex + 1;
}
const filter = options.filter;
for (; i < n; i++) {
if (~multiDragElements.indexOf(children[i])) continue;
// Check if element is draggable
if (!closest(children[i], options.draggable, parentEl, false)) continue;
// Check if element is filtered
const filtered = filter && (typeof filter === 'function' ?
filter.call(sortable, evt, children[i], sortable) :
filter.split(',').some((criteria) => {
return closest(children[i], criteria.trim(), parentEl, false);
}));
if (filtered) continue;
toggleClass(children[i], options.selectedClass, true);
multiDragElements.push(children[i]);
dispatchEvent({
sortable,
rootEl,
name: 'select',
targetEl: children[i],
originalEvent: evt
});
}
}
} else {
lastMultiDragSelect = dragEl;
}
multiDragSortable = toSortable;
} else {
multiDragElements.splice(multiDragElements.indexOf(dragEl), 1);
lastMultiDragSelect = null;
dispatchEvent({
sortable,
rootEl,
name: 'deselect',
targetEl: dragEl,
originalEvent: evt
});
}
}
// Multi-drag drop
if (dragStarted && this.isMultiDrag) {
folding = false;
// Do not "unfold" after around dragEl if reverted
if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
let dragRect = getRect(dragEl),
multiDragIndex = index(dragEl, ':not(.' + this.options.selectedClass + ')');
if (!initialFolding && options.animation) dragEl.thisAnimationDuration = null;
toSortable.captureAnimationState();
if (!initialFolding) {
if (options.animation) {
dragEl.fromRect = dragRect;
multiDragElements.forEach(multiDragElement => {
multiDragElement.thisAnimationDuration = null;
if (multiDragElement !== dragEl) {
let rect = folding ? getRect(multiDragElement) : dragRect;
multiDragElement.fromRect = rect;
// Prepare unfold animation
toSortable.addAnimationState({
target: multiDragElement,
rect: rect
});
}
});
}
// Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert
// properly they must all be removed
removeMultiDragElements();
multiDragElements.forEach(multiDragElement => {
if (children[multiDragIndex]) {
parentEl.insertBefore(multiDragElement, children[multiDragIndex]);
} else {
parentEl.appendChild(multiDragElement);
}
multiDragIndex++;
});
// If initial folding is done, the elements may have changed position because they are now
// unfolding around dragEl, even though dragEl may not have his index changed, so update event
// must be fired here as Sortable will not.
if (oldIndex === index(dragEl)) {
let update = false;
multiDragElements.forEach(multiDragElement => {
if (multiDragElement.sortableIndex !== index(multiDragElement)) {
update = true;
return;
}
});
if (update) {
dispatchSortableEvent('update');
dispatchSortableEvent('sort');
}
}
}
// Must be done after capturing individual rects (scroll bar)
multiDragElements.forEach(multiDragElement => {
unsetRect(multiDragElement);
});
toSortable.animateAll();
}
multiDragSortable = toSortable;
}
// Remove clones if necessary
if (rootEl === parentEl || (putSortable && putSortable.lastPutMode !== 'clone')) {
multiDragClones.forEach(clone => {
clone.parentNode && clone.parentNode.removeChild(clone);
});
}
},
nullingGlobal() {
this.isMultiDrag =
dragStarted = false;
multiDragClones.length = 0;
},
destroyGlobal() {
this._deselectMultiDrag();
off(document, 'pointerup', this._deselectMultiDrag);
off(document, 'mouseup', this._deselectMultiDrag);
off(document, 'touchend', this._deselectMultiDrag);
off(document, 'keydown', this._checkKeyDown);
off(document, 'keyup', this._checkKeyUp);
},
_deselectMultiDrag(evt) {
if (typeof dragStarted !== "undefined" && dragStarted) return;
// Only deselect if selection is in this sortable
if (multiDragSortable !== this.sortable) return;
// Only deselect if target is not item in this sortable
if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return;
// Only deselect if left click
if (evt && evt.button !== 0) return;
while (multiDragElements.length) {
let el = multiDragElements[0];
toggleClass(el, this.options.selectedClass, false);
multiDragElements.shift();
dispatchEvent({
sortable: this.sortable,
rootEl: this.sortable.el,
name: 'deselect',
targetEl: el,
originalEvent: evt
});
}
},
_checkKeyDown(evt) {
if (evt.key === this.options.multiDragKey) {
this.multiDragKeyDown = true;
}
},
_checkKeyUp(evt) {
if (evt.key === this.options.multiDragKey) {
this.multiDragKeyDown = false;
}
}
};
return Object.assign(MultiDrag, {
// Static methods & properties
pluginName: 'multiDrag',
utils: {
/**
* Selects the provided multi-drag item
* @param {HTMLElement} el The element to be selected
*/
select(el) {
let sortable = el.parentNode[expando];
if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return;
if (multiDragSortable && multiDragSortable !== sortable) {
multiDragSortable.multiDrag._deselectMultiDrag();
multiDragSortable = sortable;
}
toggleClass(el, sortable.options.selectedClass, true);
multiDragElements.push(el);
},
/**
* Deselects the provided multi-drag item
* @param {HTMLElement} el The element to be deselected
*/
deselect(el) {
let sortable = el.parentNode[expando],
index = multiDragElements.indexOf(el);
if (!sortable || !sortable.options.multiDrag || !~index) return;
toggleClass(el, sortable.options.selectedClass, false);
multiDragElements.splice(index, 1);
}
},
eventProperties() {
const oldIndicies = [],
newIndicies = [];
multiDragElements.forEach(multiDragElement => {
oldIndicies.push({
multiDragElement,
index: multiDragElement.sortableIndex
});
// multiDragElements will already be sorted if folding
let newIndex;
if (folding && multiDragElement !== dragEl) {
newIndex = -1;
} else if (folding) {
newIndex = index(multiDragElement, ':not(.' + this.options.selectedClass + ')');
} else {
newIndex = index(multiDragElement);
}
newIndicies.push({
multiDragElement,
index: newIndex
});
});
return {
items: [...multiDragElements],
clones: [...multiDragClones],
oldIndicies,
newIndicies
};
},
optionListeners: {
multiDragKey(key) {
key = key.toLowerCase();
if (key === 'ctrl') {
key = 'Control';
} else if (key.length > 1) {
key = key.charAt(0).toUpperCase() + key.substr(1);
}
return key;
}
}
});
}
function insertMultiDragElements(clonesInserted, rootEl) {
multiDragElements.forEach((multiDragElement, i) => {
let target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
if (target) {
rootEl.insertBefore(multiDragElement, target);
} else {
rootEl.appendChild(multiDragElement);
}
});
}
/**
* Insert multi-drag clones
* @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted
* @param {HTMLElement} rootEl
*/
function insertMultiDragClones(elementsInserted, rootEl) {
multiDragClones.forEach((clone, i) => {
let target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];
if (target) {
rootEl.insertBefore(clone, target);
} else {
rootEl.appendChild(clone);
}
});
}
function removeMultiDragElements() {
multiDragElements.forEach(multiDragElement => {
if (multiDragElement === dragEl) return;
multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
});
}
export default MultiDragPlugin;

View File

@@ -0,0 +1,97 @@
## MultiDrag Plugin
This plugin allows users to select multiple items within a sortable at once, and drag them as one item.
Once placed, the items will unfold into their original order, but all beside each other at the new position.
[Read More](https://github.com/SortableJS/Sortable/wiki/Dragging-Multiple-Items-in-Sortable)
Demo: https://jsbin.com/wopavom/edit?js,output
---
### Mounting
```js
import { Sortable, MultiDrag } from 'sortablejs';
Sortable.mount(new MultiDrag());
```
---
### Options
```js
new Sortable(el, {
multiDrag: true, // Enable the plugin
selectedClass: "sortable-selected", // Class name for selected item
multiDragKey: null, // Key that must be down for items to be selected
avoidImplicitDeselect: false, // true - if you don't want to deselect items on outside click
// Called when an item is selected
onSelect: function(/**Event*/evt) {
evt.item // The selected item
},
// Called when an item is deselected
onDeselect: function(/**Event*/evt) {
evt.item // The deselected item
}
});
```
---
#### `multiDragKey` option
The key that must be down for multiple items to be selected. The default is `null`, meaning no key must be down.
For special keys, such as the <kbd>CTRL</kbd> key, simply specify the option as `'CTRL'` (casing does not matter).
---
#### `selectedClass` option
Class name for the selected item(s) if multiDrag is enabled. Defaults to `sortable-selected`.
```css
.selected {
background-color: #f9c7c8;
border: solid red 1px;
}
```
```js
Sortable.create(list, {
multiDrag: true,
selectedClass: "selected"
});
```
---
### Event Properties
- items:`HTMLElement[]` — Array of selected items, or empty
- clones:`HTMLElement[]` — Array of clones, or empty
- oldIndicies:`Index[]` — Array containing information on the old indicies of the selected elements.
- newIndicies:`Index[]` — Array containing information on the new indicies of the selected elements.
#### Index Object
- element:`HTMLElement` — The element whose index is being given
- index:`Number` — The index of the element
#### Note on `newIndicies`
For any event that is fired during sorting, the index of any selected element that is not the main dragged element is given as `-1`.
This is because it has either been removed from the DOM, or because it is in a folding animation (folding to the dragged element) and will be removed after this animation is complete.
---
### Sortable.utils
* select(el:`HTMLElement`) — select the given multi-drag item
* deselect(el:`HTMLElement`) — deselect the given multi-drag item

View File

@@ -0,0 +1 @@
export { default } from './MultiDrag.js';

View File

@@ -0,0 +1,79 @@
import { getChild } from '../../src/utils.js';
const drop = function({
originalEvent,
putSortable,
dragEl,
activeSortable,
dispatchSortableEvent,
hideGhostForTarget,
unhideGhostForTarget
}) {
if (!originalEvent) return;
let toSortable = putSortable || activeSortable;
hideGhostForTarget();
let touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;
let target = document.elementFromPoint(touch.clientX, touch.clientY);
unhideGhostForTarget();
if (toSortable && !toSortable.el.contains(target)) {
dispatchSortableEvent('spill');
this.onSpill({ dragEl, putSortable });
}
};
function Revert() {}
Revert.prototype = {
startIndex: null,
dragStart({ oldDraggableIndex }) {
this.startIndex = oldDraggableIndex;
},
onSpill({ dragEl, putSortable }) {
this.sortable.captureAnimationState();
if (putSortable) {
putSortable.captureAnimationState();
}
let nextSibling = getChild(this.sortable.el, this.startIndex, this.options);
if (nextSibling) {
this.sortable.el.insertBefore(dragEl, nextSibling);
} else {
this.sortable.el.appendChild(dragEl);
}
this.sortable.animateAll();
if (putSortable) {
putSortable.animateAll();
}
},
drop
};
Object.assign(Revert, {
pluginName: 'revertOnSpill'
});
function Remove() {}
Remove.prototype = {
onSpill({ dragEl, putSortable }) {
const parentSortable = putSortable || this.sortable;
parentSortable.captureAnimationState();
dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
parentSortable.animateAll();
},
drop
};
Object.assign(Remove, {
pluginName: 'removeOnSpill'
});
export default [Remove, Revert];
export {
Remove as RemoveOnSpill,
Revert as RevertOnSpill
};

View File

@@ -0,0 +1,60 @@
# OnSpill Plugins
This file contains two seperate plugins, RemoveOnSpill and RevertOnSpill. They can be imported individually, or the default export (an array of both plugins) can be passed to `Sortable.mount` as well.
**These plugins are default plugins, and are included in the default UMD and ESM builds of Sortable**
---
### Mounting
```js
import { Sortable, OnSpill } from 'sortablejs/modular/sortable.core.esm';
Sortable.mount(OnSpill);
```
---
## RevertOnSpill Plugin
This plugin, when enabled, will cause the dragged item to be reverted to it's original position if it is spilled (ie. it is dropped outside of a valid Sortable drop target)
### Options
```js
new Sortable(el, {
revertOnSpill: true, // Enable plugin
// Called when item is spilled
onSpill: function(/**Event*/evt) {
evt.item // The spilled item
}
});
```
---
## RemoveOnSpill Plugin
This plugin, when enabled, will cause the dragged item to be removed from the DOM if it is spilled (ie. it is dropped outside of a valid Sortable drop target)
---
### Options
```js
new Sortable(el, {
removeOnSpill: true, // Enable plugin
// Called when item is spilled
onSpill: function(/**Event*/evt) {
evt.item // The spilled item
}
});
```

View File

@@ -0,0 +1 @@
export { default, RemoveOnSpill, RevertOnSpill } from './OnSpill.js';

View File

@@ -0,0 +1,178 @@
# Creating Sortable Plugins
Sortable plugins are plugins that can be directly mounted to the Sortable class. They are a powerful way of modifying the default behaviour of Sortable beyond what simply using events alone allows. To mount your plugin to Sortable, it must pass a constructor function to the `Sortable.mount` function. This constructor function will be called (with the `new` keyword in front of it) whenever a Sortable instance with your plugin enabled is initialized. The constructor function will be called with the parameters `sortable` and `el`, which is the HTMLElement that the Sortable is being initialized on. This means that there will be a new instance of your plugin each time it is enabled in a Sortable.
## Constructor Parameters
`sortable: Sortable` — The sortable that the plugin is being initialized on
`el: HTMLElement` — The element that the sortable is being initialized on
`options: Object` — The options object that the user has passed into Sortable (not merged with defaults yet)
## Static Properties
The constructor function passed to `Sortable.mount` may contain several static properties and methods. The following static properties may be defined:
`pluginName: String` (Required)
The name of the option that the user will use in their sortable's options to enable the plugin. Should start with a lower case and be camel-cased. For example: `'multiDrag'`. This is also the property name that the plugin's instance will be under in a sortable instance (ex. `sortableInstance.multiDrag`).
`utils: Object`
Object containing functions that will be added to the `Sortable.utils` static object on the Sortable class.
`eventOptions(eventName: String): Function`
A function that is called whenever Sortable fires an event. This function should return an object to be combined with the event object that Sortable will emit. The function will be called in the context of the instance of the plugin on the Sortable that is firing the event (ie. the `this` keyword will be the plugin instance).
`initializeByDefault: Boolean`
Determines whether or not the plugin will always be initialized on every new Sortable instance. If this option is enabled, it does not mean that by default the plugin will be enabled on the Sortable - this must still be done in the options via the plugin's `pluginName`, or it can be enabled by default if your plugin specifies it's pluginName as a default option that is truthy. Since the plugin will already be initialized on every Sortable instance, it can also be enabled dynamically via `sortableInstance.option('pluginName', true)`.
It is a good idea to have this option set to `false` if the plugin modifies the behaviour of Sortable in such a way that enabling or disabling the plugin dynamically could cause it to break. Likewise, this option should be disabled if the plugin should only be instantiated on Sortables in which that plugin is enabled.
This option defaults to `true`.
`optionListeners: Object`
An object that may contain event listeners that are fired when a specific option is updated.
These listeners are useful because the user's provided options are not necessarily unchanging once the plugin is initialized, and could be changed dynamically via the `option()` method.
The listener will be fired in the context of the instance of the plugin that it is being changed in (ie. the `this` keyword will be the instance of your plugin).
The name of the method should match the name of the option it listens for. The new value of the option will be passed in as an argument, and any returned value will be what the option is stored as. If no value is returned, the option will be stored as the value the user provided.
Example:
```js
Plugin.name = 'generateTitle';
Plugin.optionListeners = {
// Listen for option 'generateTitle'
generateTitle: function(title) {
// Store the option in all caps
return title.toUpperCase();
// OR save it to this instance of your plugin as a private field.
// This way it can be accessed in events, but will not modify the user's options.
this.titleAllCaps = title.toUpperCase();
}
};
```
## Plugin Options
Plugins may have custom default options or may override the defaults of other options. In order to do this, there must be a `defaults` object on the initialized plugin. This can be set in the plugin's prototype, or during the initialization of the plugin (when the `el` is available). For example:
```js
function myPlugin(sortable, el, options) {
this.defaults = {
color: el.style.backgroundColor
};
}
Sortable.mount(myPlugin);
```
## Plugin Events
### Context
The events will be fired in the context of their own parent object (ie. context is not changed), however the plugin instance's Sortable instance is available under `this.sortable`. Likewise, the options are available under `this.options`.
### Event List
The following table contains details on the events that a plugin may handle in the prototype of the plugin's constructor function.
| Event Name | Description | Cancelable? | Cancel Behaviour | Event Type | Custom Event Object Properties |
|---------------------------|------------------------------------------------------------------------------------------------------------------|-------------|----------------------------------------------------|------------|-------------------------------------------------------------------------|
| filter | Fired when the element is filtered, and dragging is therefore canceled | No | - | Normal | None |
| delayStart | Fired when the delay starts, even if there is no delay | Yes | Cancels sorting | Normal | None |
| delayEnded | Fired when the delay ends, even if there is no delay | Yes | Cancels sorting | Normal | None |
| setupClone | Fired when Sortable clones the dragged element | Yes | Cancels normal clone setup | Normal | None |
| dragStart | Fired when the dragging is first started | Yes | Cancels sorting | Normal | None |
| clone | Fired when the clone is inserted into the DOM (if `removeCloneOnHide: false`). Tick after dragStart. | Yes | Cancels normal clone insertion & hiding | Normal | None |
| dragStarted | Fired tick after dragStart | No | - | Normal | None |
| dragOver | Fired when the user drags over a sortable | Yes | Cancels normal dragover behaviour | DragOver | None |
| dragOverValid | Fired when the user drags over a sortable that the dragged item can be inserted into | Yes | Cancels normal valid dragover behaviour | DragOver | None |
| revert | Fired when the dragged item is reverted to it's original position when entering it's `sort:false` root | Yes | Cancels normal reverting, but is still completed() | DragOver | None |
| dragOverCompleted | Fired when dragOver is completed (ie. bubbling is disabled). To check if inserted, use `inserted` even property. | No | - | DragOver | `insertion: Boolean` — Whether or not the dragged element was inserted |
| dragOverAnimationCapture | Fired right before the animation state is captured in dragOver | No | - | DragOver | None |
| dragOverAnimationComplete | Fired after the animation is completed after a dragOver insertion | No | - | DragOver | None |
| drop | Fired on drop | Yes | Cancels normal drop behavior | Normal | None |
| nulling | Fired when the plugin should preform cleanups, once all drop events have fired | No | - | Normal | None |
| destroy | Fired when Sortable is destroyed | No | - | Normal | None |
### Global Events
Normally, an event will only be fired in a plugin if the plugin is enabled on the Sortable from which the event is being fired. However, it sometimes may be desirable for a plugin to listen in on an event from Sortables in which it is not enabled on. This is possible with global events. For an event to be global, simply add the suffix 'Global' to the event's name (casing matters) (eg. `dragStartGlobal`).
Please note that your plugin must be initialized on any Sortable from which it expects to recieve events, and that includes global events. In other words, you will want to keep the `initializeByDefault` option as it's default `true` value if your plugin needs to recieve events from Sortables it is not enabled on.
Please also note that if both normal and global event handlers are set, the global event handler will always be fired before the regular one.
### Event Object
An object with the following properties is passed as an argument to each plugin event when it is fired.
#### Properties:
`dragEl: HTMLElement` — The element being dragged
`parentEl: HTMLElement` — The element that the dragged element is currently in
`ghostEl: HTMLElement|undefined` — If using fallback, the element dragged under the cursor (undefined until after `dragStarted` plugin event)
`rootEl: HTMLElement` — The element that the dragged element originated from
`nextEl: HTMLElement` — The original next sibling of dragEl
`cloneEl: HTMLElement|undefined` — The clone element (undefined until after `setupClone` plugin event)
`cloneHidden: Boolean` — Whether or not the clone is hidden
`dragStarted: Boolean` — Boolean indicating whether or not the dragStart event has fired
`putSortable: Sortable|undefined` — The element that dragEl is dragged into from it's root, otherwise undefined
`activeSortable: Sortable` — The active Sortable instance
`originalEvent: Event` — The original HTML event corresponding to the Sortable event
`oldIndex: Number` — The old index of dragEl
`oldDraggableIndex: Number` — The old index of dragEl, only counting draggable elements
`newIndex: Number` — The new index of dragEl
`newDraggableIndex: Number` — The new index of dragEl, only counting draggable elements
#### Methods:
`cloneNowHidden()` — Function to be called if the plugin has hidden the clone
`cloneNowShown()` — Function to be called if the plugin has shown the clone
`hideGhostForTarget()` — Hides the fallback ghost element if CSS pointer-events are not available. Call this before using document.elementFromPoint at the mouse position.
`unhideGhostForTarget()` — Unhides the ghost element. To be called after `hideGhostForTarget()`.
`dispatchSortableEvent(eventName: String)` — Function that can be used to emit an event on the current sortable while sorting, with all usual event properties set (eg. indexes, rootEl, cloneEl, originalEvent, etc.).
### DragOverEvent Object
This event is passed to dragover events, and extends the normal event object.
#### Properties:
`isOwner: Boolean` — Whether or not the dragged over sortable currently contains the dragged element
`axis: String` — Direction of the dragged over sortable, `'vertical'` or `'horizontal'`
`revert: Boolean` — Whether or not the dragged element is being reverted to it's original position from another position
`dragRect: DOMRect` — DOMRect of the dragged element
`targetRect: DOMRect` — DOMRect of the target element
`canSort: Boolean` — Whether or not sorting is enabled in the dragged over sortable
`fromSortable: Sortable` — The sortable that the dragged element is coming from
`target: HTMLElement` — The sortable item that is being dragged over
#### Methods:
`onMove(target: HTMLElement, after: Boolean): Boolean|Number` — Calls the `onMove` function the user specified in the options
`changed()` — Fires the `onChange` event with event properties preconfigured
`completed(insertion: Boolean)` — Should be called when dragover has "completed", meaning bubbling should be stopped. If `insertion` is `true`, Sortable will treat it as if the dragged element was inserted into the sortable, and hide/show clone, set ghost class, animate, etc.

View File

@@ -0,0 +1,55 @@
## Swap Plugin
This plugin modifies the behaviour of Sortable to allow for items to be swapped with eachother rather than sorted. Once dragging starts, the user can drag over other items and there will be no change in the elements. However, the item that the user drops on will be swapped with the originally dragged item.
Demo: https://jsbin.com/yejehog/edit?html,js,output
---
### Mounting
```js
import { Sortable, Swap } from 'sortablejs/modular/sortable.core.esm';
Sortable.mount(new Swap());
```
---
### Options
```js
new Sortable(el, {
swap: true, // Enable swap mode
swapClass: "sortable-swap-highlight" // Class name for swap item (if swap mode is enabled)
});
```
---
#### `swapClass` option
Class name for the item to be swapped with, if swap mode is enabled. Defaults to `sortable-swap-highlight`.
```css
.highlighted {
background-color: #9AB6F1;
}
```
```js
Sortable.create(list, {
swap: true,
swapClass: "highlighted"
});
```
---
### Event Properties
- swapItem:`HTMLElement|undefined` — The element that the dragged element was swapped with

View File

@@ -0,0 +1,90 @@
import {
toggleClass,
index
} from '../../src/utils.js';
let lastSwapEl;
function SwapPlugin() {
function Swap() {
this.defaults = {
swapClass: 'sortable-swap-highlight'
};
}
Swap.prototype = {
dragStart({ dragEl }) {
lastSwapEl = dragEl;
},
dragOverValid({ completed, target, onMove, activeSortable, changed, cancel }) {
if (!activeSortable.options.swap) return;
let el = this.sortable.el,
options = this.options;
if (target && target !== el) {
let prevSwapEl = lastSwapEl;
if (onMove(target) !== false) {
toggleClass(target, options.swapClass, true);
lastSwapEl = target;
} else {
lastSwapEl = null;
}
if (prevSwapEl && prevSwapEl !== lastSwapEl) {
toggleClass(prevSwapEl, options.swapClass, false);
}
}
changed();
completed(true);
cancel();
},
drop({ activeSortable, putSortable, dragEl }) {
let toSortable = (putSortable || this.sortable);
let options = this.options;
lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
if (dragEl !== lastSwapEl) {
toSortable.captureAnimationState();
if (toSortable !== activeSortable) activeSortable.captureAnimationState();
swapNodes(dragEl, lastSwapEl);
toSortable.animateAll();
if (toSortable !== activeSortable) activeSortable.animateAll();
}
}
},
nulling() {
lastSwapEl = null;
}
};
return Object.assign(Swap, {
pluginName: 'swap',
eventProperties() {
return {
swapItem: lastSwapEl
};
}
});
}
function swapNodes(n1, n2) {
let p1 = n1.parentNode,
p2 = n2.parentNode,
i1, i2;
if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return;
i1 = index(n1);
i2 = index(n2);
if (p1.isEqualNode(p2) && i1 < i2) {
i2++;
}
p1.insertBefore(n2, p1.children[i1]);
p2.insertBefore(n1, p2.children[i2]);
}
export default SwapPlugin;

View File

@@ -0,0 +1 @@
export { default } from './Swap.js';

View File

@@ -0,0 +1,8 @@
import { version } from '../package.json';
export default `/**!
* Sortable ${ version }
* @author RubaXa <trash@rubaxa.org>
* @author owenm <owen23355@gmail.com>
* @license MIT
*/`;

View File

@@ -0,0 +1,17 @@
import babel from 'rollup-plugin-babel';
import json from 'rollup-plugin-json';
import resolve from 'rollup-plugin-node-resolve';
import banner from './banner.js';
export default {
output: {
banner,
name: 'Sortable'
},
plugins: [
json(),
babel(),
resolve()
]
};

View File

@@ -0,0 +1,28 @@
import build from './build.js';
export default ([
{
input: 'entry/entry-core.js',
output: Object.assign({}, build.output, {
file: 'modular/sortable.core.esm.js',
format: 'esm'
})
},
{
input: 'entry/entry-defaults.js',
output: Object.assign({}, build.output, {
file: 'modular/sortable.esm.js',
format: 'esm'
})
},
{
input: 'entry/entry-complete.js',
output: Object.assign({}, build.output, {
file: 'modular/sortable.complete.esm.js',
format: 'esm'
})
}
]).map(config => {
let buildCopy = { ...build };
return Object.assign(buildCopy, config);
});

View File

@@ -0,0 +1,11 @@
const UglifyJS = require('uglify-js'),
fs = require('fs'),
package = require('../package.json');
const banner = `/*! Sortable ${ package.version } - ${ package.license } | ${ package.repository.url } */\n`;
fs.writeFileSync(
`./Sortable.min.js`,
banner + UglifyJS.minify(fs.readFileSync(`./Sortable.js`, 'utf8')).code,
'utf8'
);

View File

@@ -0,0 +1,30 @@
const createTestCafe = require('testcafe');
// Testcafe cannot test on IE < 11
// Testcafe testing on Chrome Android is currently broken (https://github.com/DevExpress/testcafe/issues/3948)
const browsers = [
'saucelabs:Internet Explorer@11.285:Windows 10',
'saucelabs:MicrosoftEdge@16.16299:Windows 10',
'saucelabs:iPhone XS Simulator@12.2',
'saucelabs:Safari@12.0:macOS 10.14',
'chrome:headless',
'firefox:headless'
];
let testcafe;
let runner;
let failedCount;
createTestCafe(null, 8000, 8001).then((tc) => {
testcafe = tc;
runner = tc.createRunner();
return runner
.src('./tests/Sortable.compat.test.js')
.browsers(browsers)
.run();
}).then((actualFailedCount) => {
// https://testcafe-discuss.devexpress.com/t/why-circleci-marked-build-as-green-even-if-this-build-contain-failed-test/726/2
failedCount = actualFailedCount;
return testcafe.close();
}).then(() => process.exit(failedCount));

View File

@@ -0,0 +1,21 @@
const createTestCafe = require('testcafe');
let testcafe;
let runner;
let failedCount;
createTestCafe().then((tc) => {
testcafe = tc;
runner = tc.createRunner();
return runner
.src('./tests/Sortable.test.js')
.browsers('chrome:headless')
.concurrency(3)
.run();
}).then((actualFailedCount) => {
failedCount = actualFailedCount;
console.log('FAILED COUNT', actualFailedCount)
return testcafe.close();
}).then(() => process.exit(failedCount));

View File

@@ -0,0 +1,15 @@
import build from './build.js';
export default ([
{
input: 'entry/entry-complete.js',
output: Object.assign({}, build.output, {
file: './Sortable.js',
format: 'umd'
})
}
]).map(config => {
let buildCopy = { ...build };
return Object.assign(buildCopy, config);
});

View File

@@ -0,0 +1,175 @@
import { getRect, css, matrix, isRectEqual, indexOfObject } from './utils.js';
import Sortable from './Sortable.js';
export default function AnimationStateManager() {
let animationStates = [],
animationCallbackId;
return {
captureAnimationState() {
animationStates = [];
if (!this.options.animation) return;
let children = [].slice.call(this.el.children);
children.forEach(child => {
if (css(child, 'display') === 'none' || child === Sortable.ghost) return;
animationStates.push({
target: child,
rect: getRect(child)
});
let fromRect = { ...animationStates[animationStates.length - 1].rect };
// If animating: compensate for current animation
if (child.thisAnimationDuration) {
let childMatrix = matrix(child, true);
if (childMatrix) {
fromRect.top -= childMatrix.f;
fromRect.left -= childMatrix.e;
}
}
child.fromRect = fromRect;
});
},
addAnimationState(state) {
animationStates.push(state);
},
removeAnimationState(target) {
animationStates.splice(indexOfObject(animationStates, { target }), 1);
},
animateAll(callback) {
if (!this.options.animation) {
clearTimeout(animationCallbackId);
if (typeof(callback) === 'function') callback();
return;
}
let animating = false,
animationTime = 0;
animationStates.forEach((state) => {
let time = 0,
animatingThis = false,
target = state.target,
fromRect = target.fromRect,
toRect = getRect(target),
prevFromRect = target.prevFromRect,
prevToRect = target.prevToRect,
animatingRect = state.rect,
targetMatrix = matrix(target, true);
if (targetMatrix) {
// Compensate for current animation
toRect.top -= targetMatrix.f;
toRect.left -= targetMatrix.e;
}
target.toRect = toRect;
if (target.thisAnimationDuration) {
// Could also check if animatingRect is between fromRect and toRect
if (
isRectEqual(prevFromRect, toRect) &&
!isRectEqual(fromRect, toRect) &&
// Make sure animatingRect is on line between toRect & fromRect
(animatingRect.top - toRect.top) /
(animatingRect.left - toRect.left) ===
(fromRect.top - toRect.top) /
(fromRect.left - toRect.left)
) {
// If returning to same place as started from animation and on same axis
time = calculateRealTime(animatingRect, prevFromRect, prevToRect, this.options);
}
}
// if fromRect != toRect: animate
if (!isRectEqual(toRect, fromRect)) {
target.prevFromRect = fromRect;
target.prevToRect = toRect;
if (!time) {
time = this.options.animation;
}
this.animate(
target,
animatingRect,
toRect,
time
);
}
if (time) {
animating = true;
animationTime = Math.max(animationTime, time);
clearTimeout(target.animationResetTimer);
target.animationResetTimer = setTimeout(function() {
target.animationTime = 0;
target.prevFromRect = null;
target.fromRect = null;
target.prevToRect = null;
target.thisAnimationDuration = null;
}, time);
target.thisAnimationDuration = time;
}
});
clearTimeout(animationCallbackId);
if (!animating) {
if (typeof(callback) === 'function') callback();
} else {
animationCallbackId = setTimeout(function() {
if (typeof(callback) === 'function') callback();
}, animationTime);
}
animationStates = [];
},
animate(target, currentRect, toRect, duration) {
if (duration) {
css(target, 'transition', '');
css(target, 'transform', '');
let elMatrix = matrix(this.el),
scaleX = elMatrix && elMatrix.a,
scaleY = elMatrix && elMatrix.d,
translateX = (currentRect.left - toRect.left) / (scaleX || 1),
translateY = (currentRect.top - toRect.top) / (scaleY || 1);
target.animatingX = !!translateX;
target.animatingY = !!translateY;
css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)');
this.forRepaintDummy = repaint(target); // repaint
css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));
css(target, 'transform', 'translate3d(0,0,0)');
(typeof target.animated === 'number') && clearTimeout(target.animated);
target.animated = setTimeout(function () {
css(target, 'transition', '');
css(target, 'transform', '');
target.animated = false;
target.animatingX = false;
target.animatingY = false;
}, duration);
}
}
};
}
function repaint(target) {
return target.offsetWidth;
}
function calculateRealTime(animatingRect, fromRect, toRect, options) {
return (
Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) /
Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2))
) * options.animation;
}

View File

@@ -0,0 +1,12 @@
function userAgent(pattern) {
if (typeof window !== 'undefined' && window.navigator) {
return !!/*@__PURE__*/navigator.userAgent.match(pattern);
}
}
export const IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i);
export const Edge = userAgent(/Edge/i);
export const FireFox = userAgent(/firefox/i);
export const Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);
export const IOS = userAgent(/iP(ad|od|hone)/i);
export const ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i);

View File

@@ -0,0 +1,57 @@
import { IE11OrLess, Edge } from './BrowserInfo.js';
import { expando } from './utils.js';
import PluginManager from './PluginManager.js';
export default function dispatchEvent(
{
sortable, rootEl, name,
targetEl, cloneEl, toEl, fromEl,
oldIndex, newIndex,
oldDraggableIndex, newDraggableIndex,
originalEvent, putSortable, extraEventProperties
}
) {
sortable = (sortable || (rootEl && rootEl[expando]));
if (!sortable) return;
let evt,
options = sortable.options,
onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
// Support for new CustomEvent feature
if (window.CustomEvent && !IE11OrLess && !Edge) {
evt = new CustomEvent(name, {
bubbles: true,
cancelable: true
});
} else {
evt = document.createEvent('Event');
evt.initEvent(name, true, true);
}
evt.to = toEl || rootEl;
evt.from = fromEl || rootEl;
evt.item = targetEl || rootEl;
evt.clone = cloneEl;
evt.oldIndex = oldIndex;
evt.newIndex = newIndex;
evt.oldDraggableIndex = oldDraggableIndex;
evt.newDraggableIndex = newDraggableIndex;
evt.originalEvent = originalEvent;
evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;
let allEventProperties = { ...extraEventProperties, ...PluginManager.getEventProperties(name, sortable) };
for (let option in allEventProperties) {
evt[option] = allEventProperties[option];
}
if (rootEl) {
rootEl.dispatchEvent(evt);
}
if (options[onName]) {
options[onName].call(sortable, evt);
}
}

View File

@@ -0,0 +1,94 @@
let plugins = [];
const defaults = {
initializeByDefault: true
};
export default {
mount(plugin) {
// Set default static properties
for (let option in defaults) {
if (defaults.hasOwnProperty(option) && !(option in plugin)) {
plugin[option] = defaults[option];
}
}
plugins.forEach(p => {
if (p.pluginName === plugin.pluginName) {
throw (`Sortable: Cannot mount plugin ${ plugin.pluginName } more than once`);
}
});
plugins.push(plugin);
},
pluginEvent(eventName, sortable, evt) {
this.eventCanceled = false;
evt.cancel = () => {
this.eventCanceled = true;
};
const eventNameGlobal = eventName + 'Global';
plugins.forEach(plugin => {
if (!sortable[plugin.pluginName]) return;
// Fire global events if it exists in this sortable
if (
sortable[plugin.pluginName][eventNameGlobal]
) {
sortable[plugin.pluginName][eventNameGlobal]({ sortable, ...evt });
}
// Only fire plugin event if plugin is enabled in this sortable,
// and plugin has event defined
if (
sortable.options[plugin.pluginName] &&
sortable[plugin.pluginName][eventName]
) {
sortable[plugin.pluginName][eventName]({ sortable, ...evt });
}
});
},
initializePlugins(sortable, el, defaults, options) {
plugins.forEach(plugin => {
const pluginName = plugin.pluginName;
if (!sortable.options[pluginName] && !plugin.initializeByDefault) return;
let initialized = new plugin(sortable, el, sortable.options);
initialized.sortable = sortable;
initialized.options = sortable.options;
sortable[pluginName] = initialized;
// Add default options from plugin
Object.assign(defaults, initialized.defaults);
});
for (let option in sortable.options) {
if (!sortable.options.hasOwnProperty(option)) continue;
let modified = this.modifyOption(sortable, option, sortable.options[option]);
if (typeof(modified) !== 'undefined') {
sortable.options[option] = modified;
}
}
},
getEventProperties(name, sortable) {
let eventProperties = {};
plugins.forEach(plugin => {
if (typeof(plugin.eventProperties) !== 'function') return;
Object.assign(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name));
});
return eventProperties;
},
modifyOption(sortable, name, value) {
let modifiedValue;
plugins.forEach(plugin => {
// Plugin must exist on the Sortable
if (!sortable[plugin.pluginName]) return;
// If static option listener exists for this option, call in the context of the Sortable's instance of this plugin
if (plugin.optionListeners && typeof(plugin.optionListeners[name]) === 'function') {
modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value);
}
});
return modifiedValue;
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,595 @@
import { IE11OrLess } from './BrowserInfo.js';
import Sortable from './Sortable.js';
const captureMode = {
capture: false,
passive: false
};
function on(el, event, fn) {
el.addEventListener(event, fn, !IE11OrLess && captureMode);
}
function off(el, event, fn) {
el.removeEventListener(event, fn, !IE11OrLess && captureMode);
}
function matches(/**HTMLElement*/el, /**String*/selector) {
if (!selector) return;
selector[0] === '>' && (selector = selector.substring(1));
if (el) {
try {
if (el.matches) {
return el.matches(selector);
} else if (el.msMatchesSelector) {
return el.msMatchesSelector(selector);
} else if (el.webkitMatchesSelector) {
return el.webkitMatchesSelector(selector);
}
} catch(_) {
return false;
}
}
return false;
}
function getParentOrHost(el) {
return (el.host && el !== document && el.host.nodeType && el.host !== el)
? el.host
: el.parentNode;
}
function closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx, includeCTX) {
if (el) {
ctx = ctx || document;
do {
if (
selector != null &&
(
selector[0] === '>' ?
el.parentNode === ctx && matches(el, selector) :
matches(el, selector)
) ||
includeCTX && el === ctx
) {
return el;
}
if (el === ctx) break;
/* jshint boss:true */
} while (el = getParentOrHost(el));
}
return null;
}
const R_SPACE = /\s+/g;
function toggleClass(el, name, state) {
if (el && name) {
if (el.classList) {
el.classList[state ? 'add' : 'remove'](name);
}
else {
let className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
}
}
}
function css(el, prop, val) {
let style = el && el.style;
if (style) {
if (val === void 0) {
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '');
}
else if (el.currentStyle) {
val = el.currentStyle;
}
return prop === void 0 ? val : val[prop];
}
else {
if (!(prop in style) && prop.indexOf('webkit') === -1) {
prop = '-webkit-' + prop;
}
style[prop] = val + (typeof val === 'string' ? '' : 'px');
}
}
}
function matrix(el, selfOnly) {
let appliedTransforms = '';
if (typeof(el) === 'string') {
appliedTransforms = el;
} else {
do {
let transform = css(el, 'transform');
if (transform && transform !== 'none') {
appliedTransforms = transform + ' ' + appliedTransforms;
}
/* jshint boss:true */
} while (!selfOnly && (el = el.parentNode));
}
const matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;
/*jshint -W056 */
return matrixFn && (new matrixFn(appliedTransforms));
}
function find(ctx, tagName, iterator) {
if (ctx) {
let list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
if (iterator) {
for (; i < n; i++) {
iterator(list[i], i);
}
}
return list;
}
return [];
}
function getWindowScrollingElement() {
let scrollingElement = document.scrollingElement;
if (scrollingElement) {
return scrollingElement
} else {
return document.documentElement
}
}
/**
* Returns the "bounding client rect" of given element
* @param {HTMLElement} el The element whose boundingClientRect is wanted
* @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container
* @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr
* @param {[Boolean]} undoScale Whether the container's scale() should be undone
* @param {[HTMLElement]} container The parent the element will be placed in
* @return {Object} The boundingClientRect of el, with specified adjustments
*/
function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
if (!el.getBoundingClientRect && el !== window) return;
let elRect,
top,
left,
bottom,
right,
height,
width;
if (el !== window && el.parentNode && el !== getWindowScrollingElement()) {
elRect = el.getBoundingClientRect();
top = elRect.top;
left = elRect.left;
bottom = elRect.bottom;
right = elRect.right;
height = elRect.height;
width = elRect.width;
} else {
top = 0;
left = 0;
bottom = window.innerHeight;
right = window.innerWidth;
height = window.innerHeight;
width = window.innerWidth;
}
if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) {
// Adjust for translate()
container = container || el.parentNode;
// solves #1123 (see: https://stackoverflow.com/a/37953806/6088312)
// Not needed on <= IE11
if (!IE11OrLess) {
do {
if (
container &&
container.getBoundingClientRect &&
(
css(container, 'transform') !== 'none' ||
relativeToNonStaticParent &&
css(container, 'position') !== 'static'
)
) {
let containerRect = container.getBoundingClientRect();
// Set relative to edges of padding box of container
top -= containerRect.top + parseInt(css(container, 'border-top-width'));
left -= containerRect.left + parseInt(css(container, 'border-left-width'));
bottom = top + elRect.height;
right = left + elRect.width;
break;
}
/* jshint boss:true */
} while (container = container.parentNode);
}
}
if (undoScale && el !== window) {
// Adjust for scale()
let elMatrix = matrix(container || el),
scaleX = elMatrix && elMatrix.a,
scaleY = elMatrix && elMatrix.d;
if (elMatrix) {
top /= scaleY;
left /= scaleX;
width /= scaleX;
height /= scaleY;
bottom = top + height;
right = left + width;
}
}
return {
top: top,
left: left,
bottom: bottom,
right: right,
width: width,
height: height
};
}
/**
* Returns the content rect of the element (bounding rect minus border and padding)
* @param {HTMLElement} el
*/
function getContentRect(el) {
let rect = getRect(el);
const paddingLeft = parseInt(css(el, 'padding-left')),
paddingTop = parseInt(css(el, 'padding-top')),
paddingRight = parseInt(css(el, 'padding-right')),
paddingBottom = parseInt(css(el, 'padding-bottom'));
rect.top += paddingTop + parseInt(css(el, 'border-top-width'));
rect.left += paddingLeft + parseInt(css(el, 'border-left-width'));
// Client Width/Height includes padding only
rect.width = el.clientWidth - paddingLeft - paddingRight;
rect.height = el.clientHeight - paddingTop - paddingBottom;
rect.bottom = rect.top + rect.height;
rect.right = rect.left + rect.width;
return rect;
}
/**
* Checks if a side of an element is scrolled past a side of its parents
* @param {HTMLElement} el The element who's side being scrolled out of view is in question
* @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')
* @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')
* @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
*/
function isScrolledPast(el, elSide, parentSide) {
let parent = getParentAutoScrollElement(el, true),
elSideVal = getRect(el)[elSide];
/* jshint boss:true */
while (parent) {
let parentSideVal = getRect(parent)[parentSide],
visible;
if (parentSide === 'top' || parentSide === 'left') {
visible = elSideVal >= parentSideVal;
} else {
visible = elSideVal <= parentSideVal;
}
if (!visible) return parent;
if (parent === getWindowScrollingElement()) break;
parent = getParentAutoScrollElement(parent, false);
}
return false;
}
/**
* Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
* and non-draggable elements
* @param {HTMLElement} el The parent element
* @param {Number} childNum The index of the child
* @param {Object} options Parent Sortable's options
* @return {HTMLElement} The child at index childNum, or null if not found
*/
function getChild(el, childNum, options, includeDragEl) {
let currentChild = 0,
i = 0,
children = el.children;
while (i < children.length) {
if (
children[i].style.display !== 'none' &&
children[i] !== Sortable.ghost &&
(includeDragEl || children[i] !== Sortable.dragged) &&
closest(children[i], options.draggable, el, false)
) {
if (currentChild === childNum) {
return children[i];
}
currentChild++;
}
i++;
}
return null;
}
/**
* Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
* @param {HTMLElement} el Parent element
* @param {selector} selector Any other elements that should be ignored
* @return {HTMLElement} The last child, ignoring ghostEl
*/
function lastChild(el, selector) {
let last = el.lastElementChild;
while (
last &&
(
last === Sortable.ghost ||
css(last, 'display') === 'none' ||
selector && !matches(last, selector)
)
) {
last = last.previousElementSibling;
}
return last || null;
}
/**
* Returns the index of an element within its parent for a selected set of
* elements
* @param {HTMLElement} el
* @param {selector} selector
* @return {number}
*/
function index(el, selector) {
let index = 0;
if (!el || !el.parentNode) {
return -1;
}
/* jshint boss:true */
while (el = el.previousElementSibling) {
if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && el !== Sortable.clone && (!selector || matches(el, selector))) {
index++;
}
}
return index;
}
/**
* Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
* The value is returned in real pixels.
* @param {HTMLElement} el
* @return {Array} Offsets in the format of [left, top]
*/
function getRelativeScrollOffset(el) {
let offsetLeft = 0,
offsetTop = 0,
winScroller = getWindowScrollingElement();
if (el) {
do {
let elMatrix = matrix(el),
scaleX = elMatrix.a,
scaleY = elMatrix.d;
offsetLeft += el.scrollLeft * scaleX;
offsetTop += el.scrollTop * scaleY;
} while (el !== winScroller && (el = el.parentNode));
}
return [offsetLeft, offsetTop];
}
/**
* Returns the index of the object within the given array
* @param {Array} arr Array that may or may not hold the object
* @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
* @return {Number} The index of the object in the array, or -1
*/
function indexOfObject(arr, obj) {
for (let i in arr) {
if (!arr.hasOwnProperty(i)) continue;
for (let key in obj) {
if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i);
}
}
return -1;
}
function getParentAutoScrollElement(el, includeSelf) {
// skip to window
if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();
let elem = el;
let gotSelf = false;
do {
// we don't need to get elem css if it isn't even overflowing in the first place (performance)
if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
let elemCSS = css(elem);
if (
elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') ||
elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')
) {
if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();
if (gotSelf || includeSelf) return elem;
gotSelf = true;
}
}
/* jshint boss:true */
} while (elem = elem.parentNode);
return getWindowScrollingElement();
}
function extend(dst, src) {
if (dst && src) {
for (let key in src) {
if (src.hasOwnProperty(key)) {
dst[key] = src[key];
}
}
}
return dst;
}
function isRectEqual(rect1, rect2) {
return Math.round(rect1.top) === Math.round(rect2.top) &&
Math.round(rect1.left) === Math.round(rect2.left) &&
Math.round(rect1.height) === Math.round(rect2.height) &&
Math.round(rect1.width) === Math.round(rect2.width);
}
let _throttleTimeout;
function throttle(callback, ms) {
return function () {
if (!_throttleTimeout) {
let args = arguments,
_this = this;
if (args.length === 1) {
callback.call(_this, args[0]);
} else {
callback.apply(_this, args);
}
_throttleTimeout = setTimeout(function () {
_throttleTimeout = void 0;
}, ms);
}
};
}
function cancelThrottle() {
clearTimeout(_throttleTimeout);
_throttleTimeout = void 0;
}
function scrollBy(el, x, y) {
el.scrollLeft += x;
el.scrollTop += y;
}
function clone(el) {
let Polymer = window.Polymer;
let $ = window.jQuery || window.Zepto;
if (Polymer && Polymer.dom) {
return Polymer.dom(el).cloneNode(true);
}
else if ($) {
return $(el).clone(true)[0];
}
else {
return el.cloneNode(true);
}
}
function setRect(el, rect) {
css(el, 'position', 'absolute');
css(el, 'top', rect.top);
css(el, 'left', rect.left);
css(el, 'width', rect.width);
css(el, 'height', rect.height);
}
function unsetRect(el) {
css(el, 'position', '');
css(el, 'top', '');
css(el, 'left', '');
css(el, 'width', '');
css(el, 'height', '');
}
function getChildContainingRectFromElement(container, options, ghostEl) {
const rect = {};
Array.from(container.children).forEach(child => {
if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return;
const childRect = getRect(child);
rect.left = Math.min(rect.left ?? Infinity, childRect.left);
rect.top = Math.min(rect.top ?? Infinity, childRect.top);
rect.right = Math.max(rect.right ?? -Infinity, childRect.right);
rect.bottom = Math.max(rect.bottom ?? -Infinity, childRect.bottom);
});
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
rect.x = rect.left;
rect.y = rect.top;
return rect;
}
const expando = 'Sortable' + (new Date).getTime();
export {
on,
off,
matches,
getParentOrHost,
closest,
toggleClass,
css,
matrix,
find,
getWindowScrollingElement,
getRect,
isScrolledPast,
getChild,
lastChild,
index,
getRelativeScrollOffset,
indexOfObject,
getParentAutoScrollElement,
extend,
isRectEqual,
throttle,
cancelThrottle,
scrollBy,
clone,
setRect,
unsetRect,
getContentRect,
getChildContainingRectFromElement,
expando
};

224
www/bower_components/Sortable/st/app.js vendored Normal file
View File

@@ -0,0 +1,224 @@
var example1 = document.getElementById('example1'),
example2Left = document.getElementById('example2-left'),
example2Right = document.getElementById('example2-right'),
example3Left = document.getElementById('example3-left'),
example3Right = document.getElementById('example3-right'),
example4Left = document.getElementById('example4-left'),
example4Right = document.getElementById('example4-right'),
example5 = document.getElementById('example5'),
example6 = document.getElementById('example6'),
example7 = document.getElementById('example7'),
gridDemo = document.getElementById('gridDemo'),
multiDragDemo = document.getElementById('multiDragDemo'),
swapDemo = document.getElementById('swapDemo');
// Example 1 - Simple list
new Sortable(example1, {
animation: 150,
ghostClass: 'blue-background-class'
});
// Example 2 - Shared lists
new Sortable(example2Left, {
group: 'shared', // set both lists to same group
animation: 150
});
new Sortable(example2Right, {
group: 'shared',
animation: 150
});
// Example 3 - Cloning
new Sortable(example3Left, {
group: {
name: 'shared',
pull: 'clone' // To clone: set pull to 'clone'
},
animation: 150
});
new Sortable(example3Right, {
group: {
name: 'shared',
pull: 'clone'
},
animation: 150
});
// Example 4 - No Sorting
new Sortable(example4Left, {
group: {
name: 'shared',
pull: 'clone',
put: false // Do not allow items to be put into this list
},
animation: 150,
sort: false // To disable sorting: set sort to false
});
new Sortable(example4Right, {
group: 'shared',
animation: 150
});
// Example 5 - Handle
new Sortable(example5, {
handle: '.handle', // handle class
animation: 150
});
// Example 6 - Filter
new Sortable(example6, {
filter: '.filtered',
animation: 150
});
// Example 7 - Thresholds
var example7Sortable = new Sortable(example7, {
animation: 150
});
var example7SwapThreshold = 1;
var example7SwapThresholdInput = document.getElementById('example7SwapThresholdInput');
var example7SwapThresholdCode = document.getElementById('example7SwapThresholdCode');
var example7SwapThresholdIndicators = [].slice.call(document.querySelectorAll('.swap-threshold-indicator'));
var example7InvertSwapInput = document.getElementById('example7InvertSwapInput');
var example7InvertSwapCode = document.getElementById('example7InvertSwapCode');
var example7InvertedSwapThresholdIndicators = [].slice.call(document.querySelectorAll('.inverted-swap-threshold-indicator'));
var example7Squares = [].slice.call(document.querySelectorAll('.square'));
var activeIndicators = example7SwapThresholdIndicators;
var example7DirectionInput = document.getElementById('example7DirectionInput');
var example7SizeProperty = 'width';
function renderThresholdWidth(evt) {
example7SwapThreshold = Number(evt.target.value);
example7SwapThresholdCode.innerHTML = evt.target.value.indexOf('.') > -1 ? (evt.target.value + '0000').slice(0, 4) : evt.target.value;
for (var i = 0; i < activeIndicators.length; i++) {
activeIndicators[i].style[example7SizeProperty] = (evt.target.value * 100) /
(activeIndicators == example7SwapThresholdIndicators ? 1 : 2) + '%';
}
example7Sortable.option('swapThreshold', example7SwapThreshold);
}
example7SwapThresholdInput.addEventListener('input', renderThresholdWidth);
example7SwapThresholdInput.addEventListener('change', renderThresholdWidth);
example7InvertSwapInput.addEventListener('change', function(evt) {
example7Sortable.option('invertSwap', evt.target.checked);
for (var i = 0; i < activeIndicators.length; i++) {
activeIndicators[i].style.display = 'none';
}
if (evt.target.checked) {
example7InvertSwapCode.style.display = '';
activeIndicators = example7InvertedSwapThresholdIndicators;
} else {
example7InvertSwapCode.style.display = 'none';
activeIndicators = example7SwapThresholdIndicators;
}
renderThresholdWidth({
target: example7SwapThresholdInput
});
for (i = 0; i < activeIndicators.length; i++) {
activeIndicators[i].style.display = '';
}
});
function renderDirection(evt) {
for (var i = 0; i < example7Squares.length; i++) {
example7Squares[i].style.display = evt.target.value === 'h' ? 'inline-block' : 'block';
}
for (i = 0; i < example7InvertedSwapThresholdIndicators.length; i++) {
/* jshint expr:true */
evt.target.value === 'h' && (example7InvertedSwapThresholdIndicators[i].style.height = '100%');
evt.target.value === 'v' && (example7InvertedSwapThresholdIndicators[i].style.width = '100%');
}
for (i = 0; i < example7SwapThresholdIndicators.length; i++) {
if (evt.target.value === 'h') {
example7SwapThresholdIndicators[i].style.height = '100%';
example7SwapThresholdIndicators[i].style.marginLeft = '50%';
example7SwapThresholdIndicators[i].style.transform = 'translateX(-50%)';
example7SwapThresholdIndicators[i].style.marginTop = '0';
} else {
example7SwapThresholdIndicators[i].style.width = '100%';
example7SwapThresholdIndicators[i].style.marginTop = '50%';
example7SwapThresholdIndicators[i].style.transform = 'translateY(-50%)';
example7SwapThresholdIndicators[i].style.marginLeft = '0';
}
}
if (evt.target.value === 'h') {
example7SizeProperty = 'width';
example7Sortable.option('direction', 'horizontal');
} else {
example7SizeProperty = 'height';
example7Sortable.option('direction', 'vertical');
}
renderThresholdWidth({
target: example7SwapThresholdInput
});
}
example7DirectionInput.addEventListener('change', renderDirection);
renderDirection({
target: example7DirectionInput
});
// Grid demo
new Sortable(gridDemo, {
animation: 150,
ghostClass: 'blue-background-class'
});
// Nested demo
var nestedSortables = [].slice.call(document.querySelectorAll('.nested-sortable'));
// Loop through each nested sortable element
for (var i = 0; i < nestedSortables.length; i++) {
new Sortable(nestedSortables[i], {
group: 'nested',
animation: 150,
fallbackOnBody: true,
swapThreshold: 0.65
});
}
// MultiDrag demo
new Sortable(multiDragDemo, {
multiDrag: true,
selectedClass: 'selected',
fallbackTolerance: 3, // So that we can select items on mobile
animation: 150
});
// Swap demo
new Sortable(swapDemo, {
swap: true,
swapClass: 'highlight',
animation: 150
});

View File

@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
<!-- List with handle -->
<div id="listWithHandle" class="list-group">
<div class="list-group-item">
<span class="badge">14</span>
<span class="glyphicon glyphicon-move" aria-hidden="true"></span>
Drag me by the handle
</div>
<div class="list-group-item">
<span class="badge">2</span>
<span class="glyphicon glyphicon-move" aria-hidden="true"></span>
You can also select text
</div>
<div class="list-group-item">
<span class="badge">1</span>
<span class="glyphicon glyphicon-move" aria-hidden="true"></span>
Best of both worlds!
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>IFrame playground</title>
</head>
<body>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
<!-- Latest Sortable -->
<script src="../../Sortable.js"></script>
<!-- Simple List -->
<div id="simpleList" class="list-group">
<div class="list-group-item">This is <a href="http://rubaxa.github.io/Sortable/">Sortable</a></div>
<div class="list-group-item">It works with Bootstrap...</div>
<div class="list-group-item">...out of the box.</div>
<div class="list-group-item">It has support for touch devices.</div>
<div class="list-group-item">Just drag some elements around.</div>
</div>
<script>
(function () {
Sortable.create(simpleList, {group: 'shared'});
var iframe = document.createElement('iframe');
iframe.src = 'frame.html';
iframe.width = '100%';
iframe.onload = function () {
var doc = iframe.contentDocument,
list = doc.getElementById('listWithHandle');
Sortable.create(list, {group: 'shared'});
};
document.body.appendChild(iframe);
})();
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.clo,.opn,.pun{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.kwd,.tag,.typ{font-weight:700}.str{color:#060}.kwd{color:#006}.com{color:#600;font-style:italic}.typ{color:#404}.lit{color:#044}.clo,.opn,.pun{color:#440}.tag{color:#006}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

View File

@@ -0,0 +1,46 @@
!function(){/*
Copyright (C) 2006 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
"undefined"!==typeof window&&(window.PR_SHOULD_USE_CONTINUATION=!0);
(function(){function T(a){function d(e){var a=e.charCodeAt(0);if(92!==a)return a;var c=e.charAt(1);return(a=w[c])?a:"0"<=c&&"7">=c?parseInt(e.substring(1),8):"u"===c||"x"===c?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"===e||"]"===e||"^"===e?"\\"+e:e}function c(e){var c=e.substring(1,e.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));
e=[];var a="^"===c[0],b=["["];a&&b.push("^");for(var a=a?1:0,g=c.length;a<g;++a){var h=c[a];if(/\\[bdsw]/i.test(h))b.push(h);else{var h=d(h),k;a+2<g&&"-"===c[a+1]?(k=d(c[a+2]),a+=2):k=h;e.push([h,k]);65>k||122<h||(65>k||90<h||e.push([Math.max(65,h)|32,Math.min(k,90)|32]),97>k||122<h||e.push([Math.max(97,h)&-33,Math.min(k,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});c=[];g=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=g[1]+1?g[1]=Math.max(g[1],h[1]):c.push(g=h);for(a=0;a<c.length;++a)h=
c[a],b.push(f(h[0])),h[1]>h[0]&&(h[1]+1>h[0]&&b.push("-"),b.push(f(h[1])));b.push("]");return b.join("")}function m(e){for(var a=e.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),b=a.length,d=[],g=0,h=0;g<b;++g){var k=a[g];"("===k?++h:"\\"===k.charAt(0)&&(k=+k.substring(1))&&(k<=h?d[k]=-1:a[g]=f(k))}for(g=1;g<d.length;++g)-1===d[g]&&(d[g]=++E);for(h=g=0;g<b;++g)k=a[g],
"("===k?(++h,d[h]||(a[g]="(?:")):"\\"===k.charAt(0)&&(k=+k.substring(1))&&k<=h&&(a[g]="\\"+d[k]);for(g=0;g<b;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(e.ignoreCase&&q)for(g=0;g<b;++g)k=a[g],e=k.charAt(0),2<=k.length&&"["===e?a[g]=c(k):"\\"!==e&&(a[g]=k.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var E=0,q=!1,l=!1,n=0,b=a.length;n<b;++n){var p=a[n];if(p.ignoreCase)l=!0;else if(/[a-z]/i.test(p.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,
""))){q=!0;l=!1;break}}for(var w={b:8,t:9,n:10,v:11,f:12,r:13},r=[],n=0,b=a.length;n<b;++n){p=a[n];if(p.global||p.multiline)throw Error(""+p);r.push("(?:"+m(p)+")")}return new RegExp(r.join("|"),l?"gi":"g")}function U(a,d){function f(a){var b=a.nodeType;if(1==b){if(!c.test(a.className)){for(b=a.firstChild;b;b=b.nextSibling)f(b);b=a.nodeName.toLowerCase();if("br"===b||"li"===b)m[l]="\n",q[l<<1]=E++,q[l++<<1|1]=a}}else if(3==b||4==b)b=a.nodeValue,b.length&&(b=d?b.replace(/\r\n?/g,"\n"):b.replace(/[ \t\r\n]+/g,
" "),m[l]=b,q[l<<1]=E,E+=b.length,q[l++<<1|1]=a)}var c=/(?:^|\s)nocode(?:\s|$)/,m=[],E=0,q=[],l=0;f(a);return{a:m.join("").replace(/\n$/,""),c:q}}function J(a,d,f,c,m){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},c(a),m.push.apply(m,a.g))}function V(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var c=f.nodeType,d=1===c?d?a:f:3===c?W.test(f.nodeValue)?a:d:d;return d===a?void 0:d}function G(a,d){function f(a){for(var l=a.i,n=a.h,b=[l,"pln"],p=0,q=a.a.match(m)||[],r={},e=0,t=q.length;e<
t;++e){var z=q[e],v=r[z],g=void 0,h;if("string"===typeof v)h=!1;else{var k=c[z.charAt(0)];if(k)g=z.match(k[1]),v=k[0];else{for(h=0;h<E;++h)if(k=d[h],g=z.match(k[1])){v=k[0];break}g||(v="pln")}!(h=5<=v.length&&"lang-"===v.substring(0,5))||g&&"string"===typeof g[1]||(h=!1,v="src");h||(r[z]=v)}k=p;p+=z.length;if(h){h=g[1];var A=z.indexOf(h),C=A+h.length;g[2]&&(C=z.length-g[2].length,A=C-h.length);v=v.substring(5);J(n,l+k,z.substring(0,A),f,b);J(n,l+k+A,h,K(v,h),b);J(n,l+k+C,z.substring(C),f,b)}else b.push(l+
k,v)}a.g=b}var c={},m;(function(){for(var f=a.concat(d),l=[],n={},b=0,p=f.length;b<p;++b){var w=f[b],r=w[3];if(r)for(var e=r.length;0<=--e;)c[r.charAt(e)]=w;w=w[1];r=""+w;n.hasOwnProperty(r)||(l.push(w),n[r]=null)}l.push(/[\0-\uffff]/);m=T(l)})();var E=d.length;return f}function x(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var c=a.hashComments;c&&(a.cStyleComments?(1<c?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(c=a.regexLiterals){var m=(c=1<c?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
("/(?=[^/*"+c+"])(?:[^/\\x5B\\x5C"+c+"]|\\x5C"+m+"|\\x5B(?:[^\\x5C\\x5D"+c+"]|\\x5C"+m+")*(?:\\x5D|$))+/")+")")])}(c=a.types)&&f.push(["typ",c]);c=(""+a.keywords).replace(/^ | $/g,"");c.length&&f.push(["kwd",new RegExp("^(?:"+c.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);c="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(c+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,
null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(c),null]);return G(d,f)}function L(a,d,f){function c(a){var b=a.nodeType;if(1==b&&!t.test(a.className))if("br"===a.nodeName.toLowerCase())m(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)c(a);else if((3==b||4==b)&&f){var e=a.nodeValue,d=e.match(q);d&&(b=e.substring(0,d.index),a.nodeValue=b,(e=e.substring(d.index+
d[0].length))&&a.parentNode.insertBefore(l.createTextNode(e),a.nextSibling),m(a),b||a.parentNode.removeChild(a))}}function m(a){function c(a,b){var e=b?a.cloneNode(!1):a,k=a.parentNode;if(k){var k=c(k,1),d=a.nextSibling;k.appendChild(e);for(var f=d;f;f=d)d=f.nextSibling,k.appendChild(f)}return e}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=c(a.nextSibling,0);for(var e;(e=a.parentNode)&&1===e.nodeType;)a=e;b.push(a)}for(var t=/(?:^|\s)nocode(?:\s|$)/,q=/\r\n?|\n/,l=a.ownerDocument,n=l.createElement("li");a.firstChild;)n.appendChild(a.firstChild);
for(var b=[n],p=0;p<b.length;++p)c(b[p]);d===(d|0)&&b[0].setAttribute("value",d);var w=l.createElement("ol");w.className="linenums";d=Math.max(0,d-1|0)||0;for(var p=0,r=b.length;p<r;++p)n=b[p],n.className="L"+(p+d)%10,n.firstChild||n.appendChild(l.createTextNode("\u00a0")),w.appendChild(n);a.appendChild(w)}function t(a,d){for(var f=d.length;0<=--f;){var c=d[f];I.hasOwnProperty(c)?D.console&&console.warn("cannot override language handler %s",c):I[c]=a}}function K(a,d){a&&I.hasOwnProperty(a)||(a=/^\s*</.test(d)?
"default-markup":"default-code");return I[a]}function M(a){var d=a.j;try{var f=U(a.h,a.l),c=f.a;a.a=c;a.c=f.c;a.i=0;K(d,c)(a);var m=/\bMSIE\s(\d+)/.exec(navigator.userAgent),m=m&&8>=+m[1],d=/\n/g,t=a.a,q=t.length,f=0,l=a.c,n=l.length,c=0,b=a.g,p=b.length,w=0;b[p]=q;var r,e;for(e=r=0;e<p;)b[e]!==b[e+2]?(b[r++]=b[e++],b[r++]=b[e++]):e+=2;p=r;for(e=r=0;e<p;){for(var x=b[e],z=b[e+1],v=e+2;v+2<=p&&b[v+1]===z;)v+=2;b[r++]=x;b[r++]=z;e=v}b.length=r;var g=a.h;a="";g&&(a=g.style.display,g.style.display="none");
try{for(;c<n;){var h=l[c+2]||q,k=b[w+2]||q,v=Math.min(h,k),A=l[c+1],C;if(1!==A.nodeType&&(C=t.substring(f,v))){m&&(C=C.replace(d,"\r"));A.nodeValue=C;var N=A.ownerDocument,u=N.createElement("span");u.className=b[w+1];var B=A.parentNode;B.replaceChild(u,A);u.appendChild(A);f<h&&(l[c+1]=A=N.createTextNode(t.substring(v,h)),B.insertBefore(A,u.nextSibling))}f=v;f>=h&&(c+=2);f>=k&&(w+=2)}}finally{g&&(g.style.display=a)}}catch(y){D.console&&console.log(y&&y.stack||y)}}var D="undefined"!==typeof window?
window:{},B=["break,continue,do,else,for,if,return,while"],F=[[B,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],H=[F,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
O=[F,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],P=[F,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],
F=[F,"abstract,async,await,constructor,debugger,enum,eval,export,from,function,get,import,implements,instanceof,interface,let,null,of,set,undefined,var,with,yield,Infinity,NaN"],Q=[B,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],R=[B,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],
B=[B,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],S=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,W=/\S/,X=x({keywords:[H,P,O,F,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",Q,R,B],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),
I={};t(X,["default-code"]);t(G([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));t(G([["pln",/^[\s]+/,
null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);
t(G([],[["atv",/^[\s\S]+/]]),["uq.val"]);t(x({keywords:H,hashComments:!0,cStyleComments:!0,types:S}),"c cc cpp cxx cyc m".split(" "));t(x({keywords:"null,true,false"}),["json"]);t(x({keywords:P,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:S}),["cs"]);t(x({keywords:O,cStyleComments:!0}),["java"]);t(x({keywords:B,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);t(x({keywords:Q,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);t(x({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",
hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);t(x({keywords:R,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);t(x({keywords:F,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]);t(x({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,
regexLiterals:!0}),["coffee"]);t(G([],[["str",/^[\s\S]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:G,registerLangHandler:t,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,f){f=f||!1;d=d||null;var c=document.createElement("div");c.innerHTML="<pre>"+a+"</pre>";
c=c.firstChild;f&&L(c,f,!0);M({j:d,m:f,h:c,l:1,a:null,i:null,c:null,g:null});return c.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function f(){for(var c=D.PR_SHOULD_USE_CONTINUATION?b.now()+250:Infinity;p<x.length&&b.now()<c;p++){for(var d=x[p],l=g,n=d;n=n.previousSibling;){var m=n.nodeType,u=(7===m||8===m)&&n.nodeValue;if(u?!/^\??prettify\b/.test(u):3!==m||/\S/.test(n.nodeValue))break;if(u){l={};u.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){l[b]=c});break}}n=d.className;if((l!==g||r.test(n))&&
!e.test(n)){m=!1;for(u=d.parentNode;u;u=u.parentNode)if(v.test(u.tagName)&&u.className&&r.test(u.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=l.lang;if(!m){var m=n.match(w),q;!m&&(q=V(d))&&z.test(q.tagName)&&(m=q.className.match(w));m&&(m=m[1])}if(B.test(d.tagName))u=1;else var u=d.currentStyle,y=t.defaultView,u=(u=u?u.whiteSpace:y&&y.getComputedStyle?y.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===u.substring(0,3);y=l.linenums;(y="true"===y||+y)||(y=(y=n.match(/\blinenums\b(?::(\d+))?/))?
y[1]&&y[1].length?+y[1]:!0:!1);y&&L(d,y,u);M({j:m,h:d,m:y,l:u,a:null,i:null,c:null,g:null})}}}p<x.length?D.setTimeout(f,250):"function"===typeof a&&a()}for(var c=d||document.body,t=c.ownerDocument||document,c=[c.getElementsByTagName("pre"),c.getElementsByTagName("code"),c.getElementsByTagName("xmp")],x=[],q=0;q<c.length;++q)for(var l=0,n=c[q].length;l<n;++l)x.push(c[q][l]);var c=null,b=Date;b.now||(b={now:function(){return+new Date}});var p=0,w=/\blang(?:uage)?-([\w.]+)(?!\S)/,r=/\bprettyprint\b/,
e=/\bprettyprinted\b/,B=/pre|xmp/i,z=/^code$/i,v=/^(?:pre|code|xmp)$/i,g={};f()}},H=D.define;"function"===typeof H&&H.amd&&H("google-code-prettify",[],function(){return Y})})();}()

View File

@@ -0,0 +1,64 @@
!function(){/*
Copyright (C) 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (C) 2006 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
(function(){function aa(g){function r(){try{L.doScroll("left")}catch(ba){k.setTimeout(r,50);return}x("poll")}function x(r){if("readystatechange"!=r.type||"complete"==z.readyState)("load"==r.type?k:z)[B](n+r.type,x,!1),!l&&(l=!0)&&g.call(k,r.type||r)}var X=z.addEventListener,l=!1,E=!0,v=X?"addEventListener":"attachEvent",B=X?"removeEventListener":"detachEvent",n=X?"":"on";if("complete"==z.readyState)g.call(k,"lazy");else{if(z.createEventObject&&L.doScroll){try{E=!k.frameElement}catch(ba){}E&&r()}z[v](n+
"DOMContentLoaded",x,!1);z[v](n+"readystatechange",x,!1);k[v](n+"load",x,!1)}}function T(){U&&aa(function(){var g=M.length;ca(g?function(){for(var r=0;r<g;++r)(function(g){k.setTimeout(function(){k.exports[M[g]].apply(k,arguments)},0)})(r)}:void 0)})}for(var k=window,z=document,L=z.documentElement,N=z.head||z.getElementsByTagName("head")[0]||L,B="",F=z.getElementsByTagName("script"),l=F.length;0<=--l;){var O=F[l],Y=O.src.match(/^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(Y){B=Y[1]||"";O.parentNode.removeChild(O);
break}}var U=!0,H=[],P=[],M=[];B.replace(/[?&]([^&=]+)=([^&]+)/g,function(g,r,x){x=decodeURIComponent(x);r=decodeURIComponent(r);"autorun"==r?U=!/^[0fn]/i.test(x):"lang"==r?H.push(x):"skin"==r?P.push(x):"callback"==r&&M.push(x)});l=0;for(B=H.length;l<B;++l)(function(){var g=z.createElement("script");g.onload=g.onerror=g.onreadystatechange=function(){!g||g.readyState&&!/loaded|complete/.test(g.readyState)||(g.onerror=g.onload=g.onreadystatechange=null,--S,S||k.setTimeout(T,0),g.parentNode&&g.parentNode.removeChild(g),
g=null)};g.type="text/javascript";g.src="https://cdn.rawgit.com/google/code-prettify/master/loader/lang-"+encodeURIComponent(H[l])+".js";N.insertBefore(g,N.firstChild)})(H[l]);for(var S=H.length,F=[],l=0,B=P.length;l<B;++l)F.push("https://cdn.rawgit.com/google/code-prettify/master/loader/skins/"+encodeURIComponent(P[l])+".css");F.push("https://cdn.rawgit.com/google/code-prettify/master/loader/prettify.css");(function(g){function r(l){if(l!==x){var k=z.createElement("link");k.rel="stylesheet";k.type=
"text/css";l+1<x&&(k.error=k.onerror=function(){r(l+1)});k.href=g[l];N.appendChild(k)}}var x=g.length;r(0)})(F);var ca=function(){"undefined"!==typeof window&&(window.PR_SHOULD_USE_CONTINUATION=!0);var g;(function(){function r(a){function d(e){var a=e.charCodeAt(0);if(92!==a)return a;var c=e.charAt(1);return(a=k[c])?a:"0"<=c&&"7">=c?parseInt(e.substring(1),8):"u"===c||"x"===c?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);
return"\\"===e||"-"===e||"]"===e||"^"===e?"\\"+e:e}function c(e){var c=e.substring(1,e.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));e=[];var a="^"===c[0],b=["["];a&&b.push("^");for(var a=a?1:0,h=c.length;a<h;++a){var m=c[a];if(/\\[bdsw]/i.test(m))b.push(m);else{var m=d(m),p;a+2<h&&"-"===c[a+1]?(p=d(c[a+2]),a+=2):p=m;e.push([m,p]);65>p||122<m||(65>p||90<m||e.push([Math.max(65,m)|32,Math.min(p,90)|32]),97>p||122<m||
e.push([Math.max(97,m)&-33,Math.min(p,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});c=[];h=[];for(a=0;a<e.length;++a)m=e[a],m[0]<=h[1]+1?h[1]=Math.max(h[1],m[1]):c.push(h=m);for(a=0;a<c.length;++a)m=c[a],b.push(f(m[0])),m[1]>m[0]&&(m[1]+1>m[0]&&b.push("-"),b.push(f(m[1])));b.push("]");return b.join("")}function g(e){for(var a=e.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)",
"g")),b=a.length,d=[],h=0,m=0;h<b;++h){var p=a[h];"("===p?++m:"\\"===p.charAt(0)&&(p=+p.substring(1))&&(p<=m?d[p]=-1:a[h]=f(p))}for(h=1;h<d.length;++h)-1===d[h]&&(d[h]=++r);for(m=h=0;h<b;++h)p=a[h],"("===p?(++m,d[m]||(a[h]="(?:")):"\\"===p.charAt(0)&&(p=+p.substring(1))&&p<=m&&(a[h]="\\"+d[p]);for(h=0;h<b;++h)"^"===a[h]&&"^"!==a[h+1]&&(a[h]="");if(e.ignoreCase&&A)for(h=0;h<b;++h)p=a[h],e=p.charAt(0),2<=p.length&&"["===e?a[h]=c(p):"\\"!==e&&(a[h]=p.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);
return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var r=0,A=!1,q=!1,I=0,b=a.length;I<b;++I){var t=a[I];if(t.ignoreCase)q=!0;else if(/[a-z]/i.test(t.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){A=!0;q=!1;break}}for(var k={b:8,t:9,n:10,v:11,f:12,r:13},u=[],I=0,b=a.length;I<b;++I){t=a[I];if(t.global||t.multiline)throw Error(""+t);u.push("(?:"+g(t)+")")}return new RegExp(u.join("|"),q?"gi":"g")}function l(a,d){function f(a){var b=a.nodeType;if(1==b){if(!c.test(a.className)){for(b=
a.firstChild;b;b=b.nextSibling)f(b);b=a.nodeName.toLowerCase();if("br"===b||"li"===b)g[q]="\n",A[q<<1]=r++,A[q++<<1|1]=a}}else if(3==b||4==b)b=a.nodeValue,b.length&&(b=d?b.replace(/\r\n?/g,"\n"):b.replace(/[ \t\r\n]+/g," "),g[q]=b,A[q<<1]=r,r+=b.length,A[q++<<1|1]=a)}var c=/(?:^|\s)nocode(?:\s|$)/,g=[],r=0,A=[],q=0;f(a);return{a:g.join("").replace(/\n$/,""),c:A}}function k(a,d,f,c,g){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},c(a),g.push.apply(g,a.g))}function z(a){for(var d=void 0,f=a.firstChild;f;f=
f.nextSibling)var c=f.nodeType,d=1===c?d?a:f:3===c?S.test(f.nodeValue)?a:d:d;return d===a?void 0:d}function E(a,d){function f(a){for(var q=a.i,r=a.h,b=[q,"pln"],t=0,A=a.a.match(g)||[],u={},e=0,l=A.length;e<l;++e){var D=A[e],w=u[D],h=void 0,m;if("string"===typeof w)m=!1;else{var p=c[D.charAt(0)];if(p)h=D.match(p[1]),w=p[0];else{for(m=0;m<n;++m)if(p=d[m],h=D.match(p[1])){w=p[0];break}h||(w="pln")}!(m=5<=w.length&&"lang-"===w.substring(0,5))||h&&"string"===typeof h[1]||(m=!1,w="src");m||(u[D]=w)}p=t;
t+=D.length;if(m){m=h[1];var C=D.indexOf(m),G=C+m.length;h[2]&&(G=D.length-h[2].length,C=G-m.length);w=w.substring(5);k(r,q+p,D.substring(0,C),f,b);k(r,q+p+C,m,F(w,m),b);k(r,q+p+G,D.substring(G),f,b)}else b.push(q+p,w)}a.g=b}var c={},g;(function(){for(var f=a.concat(d),q=[],k={},b=0,t=f.length;b<t;++b){var n=f[b],u=n[3];if(u)for(var e=u.length;0<=--e;)c[u.charAt(e)]=n;n=n[1];u=""+n;k.hasOwnProperty(u)||(q.push(n),k[u]=null)}q.push(/[\0-\uffff]/);g=r(q)})();var n=d.length;return f}function v(a){var d=
[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&
f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var c=a.hashComments;c&&(a.cStyleComments?(1<c?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,
null]));if(c=a.regexLiterals){var g=(c=1<c?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+c+"])(?:[^/\\x5B\\x5C"+c+"]|\\x5C"+g+"|\\x5B(?:[^\\x5C\\x5D"+c+"]|\\x5C"+g+")*(?:\\x5D|$))+/")+")")])}(c=a.types)&&f.push(["typ",c]);c=(""+a.keywords).replace(/^ | $/g,"");c.length&&f.push(["kwd",
new RegExp("^(?:"+c.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);c="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(c+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(c),null]);return E(d,f)}function B(a,d,f){function c(a){var b=
a.nodeType;if(1==b&&!r.test(a.className))if("br"===a.nodeName.toLowerCase())g(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)c(a);else if((3==b||4==b)&&f){var e=a.nodeValue,d=e.match(n);d&&(b=e.substring(0,d.index),a.nodeValue=b,(e=e.substring(d.index+d[0].length))&&a.parentNode.insertBefore(q.createTextNode(e),a.nextSibling),g(a),b||a.parentNode.removeChild(a))}}function g(a){function c(a,b){var e=b?a.cloneNode(!1):a,p=a.parentNode;if(p){var p=c(p,1),d=a.nextSibling;
p.appendChild(e);for(var f=d;f;f=d)d=f.nextSibling,p.appendChild(f)}return e}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=c(a.nextSibling,0);for(var e;(e=a.parentNode)&&1===e.nodeType;)a=e;b.push(a)}for(var r=/(?:^|\s)nocode(?:\s|$)/,n=/\r\n?|\n/,q=a.ownerDocument,k=q.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var b=[k],t=0;t<b.length;++t)c(b[t]);d===(d|0)&&b[0].setAttribute("value",d);var l=q.createElement("ol");l.className="linenums";d=Math.max(0,d-1|0)||0;for(var t=
0,u=b.length;t<u;++t)k=b[t],k.className="L"+(t+d)%10,k.firstChild||k.appendChild(q.createTextNode("\u00a0")),l.appendChild(k);a.appendChild(l)}function n(a,d){for(var f=d.length;0<=--f;){var c=d[f];V.hasOwnProperty(c)?Q.console&&console.warn("cannot override language handler %s",c):V[c]=a}}function F(a,d){a&&V.hasOwnProperty(a)||(a=/^\s*</.test(d)?"default-markup":"default-code");return V[a]}function H(a){var d=a.j;try{var f=l(a.h,a.l),c=f.a;a.a=c;a.c=f.c;a.i=0;F(d,c)(a);var g=/\bMSIE\s(\d+)/.exec(navigator.userAgent),
g=g&&8>=+g[1],d=/\n/g,r=a.a,k=r.length,f=0,q=a.c,n=q.length,c=0,b=a.g,t=b.length,v=0;b[t]=k;var u,e;for(e=u=0;e<t;)b[e]!==b[e+2]?(b[u++]=b[e++],b[u++]=b[e++]):e+=2;t=u;for(e=u=0;e<t;){for(var x=b[e],z=b[e+1],w=e+2;w+2<=t&&b[w+1]===z;)w+=2;b[u++]=x;b[u++]=z;e=w}b.length=u;var h=a.h;a="";h&&(a=h.style.display,h.style.display="none");try{for(;c<n;){var m=q[c+2]||k,p=b[v+2]||k,w=Math.min(m,p),C=q[c+1],G;if(1!==C.nodeType&&(G=r.substring(f,w))){g&&(G=G.replace(d,"\r"));C.nodeValue=G;var Z=C.ownerDocument,
W=Z.createElement("span");W.className=b[v+1];var B=C.parentNode;B.replaceChild(W,C);W.appendChild(C);f<m&&(q[c+1]=C=Z.createTextNode(r.substring(w,m)),B.insertBefore(C,W.nextSibling))}f=w;f>=m&&(c+=2);f>=p&&(v+=2)}}finally{h&&(h.style.display=a)}}catch(y){Q.console&&console.log(y&&y.stack||y)}}var Q="undefined"!==typeof window?window:{},J=["break,continue,do,else,for,if,return,while"],K=[[J,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],R=[K,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],L=[K,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
M=[K,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],K=[K,"abstract,async,await,constructor,debugger,enum,eval,export,from,function,get,import,implements,instanceof,interface,let,null,of,set,undefined,var,with,yield,Infinity,NaN"],
N=[J,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],O=[J,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],J=[J,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],P=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
S=/\S/,T=v({keywords:[R,M,L,K,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",N,O,J],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),V={};n(T,["default-code"]);n(E([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));n(E([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);n(E([],[["atv",/^[\s\S]+/]]),["uq.val"]);n(v({keywords:R,hashComments:!0,cStyleComments:!0,types:P}),"c cc cpp cxx cyc m".split(" "));n(v({keywords:"null,true,false"}),["json"]);n(v({keywords:M,hashComments:!0,cStyleComments:!0,
verbatimStrings:!0,types:P}),["cs"]);n(v({keywords:L,cStyleComments:!0}),["java"]);n(v({keywords:J,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);n(v({keywords:N,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);n(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),
["perl","pl","pm"]);n(v({keywords:O,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);n(v({keywords:K,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]);n(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);n(E([],[["str",/^[\s\S]+/]]),
["regex"]);var U=Q.PR={createSimpleLexer:E,registerLangHandler:n,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,f){f=f||!1;d=d||null;var c=document.createElement("div");c.innerHTML="<pre>"+a+"</pre>";c=c.firstChild;f&&B(c,f,!0);H({j:d,m:f,h:c,l:1,a:null,i:null,c:null,g:null});
return c.innerHTML},prettyPrint:g=function(a,d){function f(){for(var c=Q.PR_SHOULD_USE_CONTINUATION?b.now()+250:Infinity;t<r.length&&b.now()<c;t++){for(var d=r[t],k=h,n=d;n=n.previousSibling;){var q=n.nodeType,l=(7===q||8===q)&&n.nodeValue;if(l?!/^\??prettify\b/.test(l):3!==q||/\S/.test(n.nodeValue))break;if(l){k={};l.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){k[b]=c});break}}n=d.className;if((k!==h||u.test(n))&&!e.test(n)){q=!1;for(l=d.parentNode;l;l=l.parentNode)if(w.test(l.tagName)&&l.className&&
u.test(l.className)){q=!0;break}if(!q){d.className+=" prettyprinted";q=k.lang;if(!q){var q=n.match(v),A;!q&&(A=z(d))&&D.test(A.tagName)&&(q=A.className.match(v));q&&(q=q[1])}if(x.test(d.tagName))l=1;else var l=d.currentStyle,y=g.defaultView,l=(l=l?l.whiteSpace:y&&y.getComputedStyle?y.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===l.substring(0,3);y=k.linenums;(y="true"===y||+y)||(y=(y=n.match(/\blinenums\b(?::(\d+))?/))?y[1]&&y[1].length?+y[1]:!0:!1);y&&B(d,y,l);H({j:q,h:d,m:y,
l:l,a:null,i:null,c:null,g:null})}}}t<r.length?Q.setTimeout(f,250):"function"===typeof a&&a()}for(var c=d||document.body,g=c.ownerDocument||document,c=[c.getElementsByTagName("pre"),c.getElementsByTagName("code"),c.getElementsByTagName("xmp")],r=[],k=0;k<c.length;++k)for(var n=0,l=c[k].length;n<l;++n)r.push(c[k][n]);var c=null,b=Date;b.now||(b={now:function(){return+new Date}});var t=0,v=/\blang(?:uage)?-([\w.]+)(?!\S)/,u=/\bprettyprint\b/,e=/\bprettyprinted\b/,x=/pre|xmp/i,D=/^code$/i,w=/^(?:pre|code|xmp)$/i,
h={};f()}},R=Q.define;"function"===typeof R&&R.amd&&R("google-code-prettify",[],function(){return U})})();return g}();S||k.setTimeout(T,0)})();}()

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,254 @@
body {
font-family: Helvetica Neue, Helvetica, Arial;
background: rgb(244,215,201); /* Old browsers */
background: -moz-linear-gradient(top, rgb(244,215,201) 0%, rgb(244,226,201) 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, rgb(244,215,201) 0%,rgb(244,226,201) 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, rgb(244,215,201) 0%,rgb(244,226,201) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
margin-bottom: 100px;
}
.header {
margin-top: 30px;
}
.header h1 {
margin-top: 10px;
}
h4 {
padding-bottom: 10px;
}
.prettyprinted {
margin-top: 5px;
border-top: none !important;
border-bottom: none !important;
border-right: none !important;
border-left: 1px solid rgba(0,0,0,.1) !important;
padding-left: 15px !important;
word-wrap: break-word !important;
overflow: default !important;
text-overflow: default !important;
}
.tinted {
background-color: #fff6b2;
}
.handle {
cursor: grab;
}
code {
color: #606;
}
.toc {
background-color: rgb(255,255,255,0.5);
border: solid #444 1px;
padding: 20px;
margin-left: auto;
margin-right: auto;
list-style: none;
}
.toc h5 {
margin-top: 8px;
}
.list-group-item:hover {
z-index: 0;
}
.input-section {
background-color: rgb(255,255,255,0.5);
padding: 20px;
}
.square-section {
background-color: rgb(255,255,255,0.5);
}
.square {
width: 20vw;
height: 20vw;
background-color: #00a2ff;
margin-top: 2vw;
margin-left: 2vw;
display: inline-block;
position: relative;
}
.swap-threshold-indicator {
background-color: #0079bf;
height: 100%;
display: inline-block;
}
.inverted-swap-threshold-indicator {
background-color: #0079bf;
height: 100%;
position: absolute;
}
.indicator-left {
left: 0;
top: 0;
}
.indicator-right {
right: 0;
bottom: 0;
}
.num-indicator {
position: absolute;
font-size: 50px;
width: 25px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
}
.grid-square {
width: 100px;
height: 100px;
display: inline-block;
background-color: #fff;
border: solid 1px rgb(0,0,0,0.2);
padding: 10px;
margin: 12px;
}
.nested-sortable, .nested-1, .nested-2, .nested-3 {
margin-top: 5px;
}
.nested-1 {
background-color: #e6e6e6;
}
.nested-2 {
background-color: #cccccc;
}
.nested-3 {
background-color: #b3b3b3;
}
.frameworks {
background-color: rgb(255,255,255,0.5);
border: solid rgb(0,0,0,0.3) 1px;
padding: 20px;
}
.frameworks h3 {
margin-top: 5px;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 3.8px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: rgba(48, 113, 169, 0);
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0.9px #000000, 0px 0px 0px #0d0d0d;
border: 1.3px solid rgba(0, 0, 0, 0.7);
height: 16px;
width: 16px;
border-radius: 49px;
background: #ffffff;
cursor: pointer;
-webkit-appearance: none;
margin-top: -4px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: rgba(54, 126, 189, 0);
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: rgba(48, 113, 169, 0);
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0.9px #000000, 0px 0px 0px #0d0d0d;
border: 1.3px solid rgba(0, 0, 0, 0.7);
height: 16px;
width: 16px;
border-radius: 49px;
background: #ffffff;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 8.4px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: rgba(42, 100, 149, 0);
border: 0.2px solid #010101;
border-radius: 2.6px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: rgba(48, 113, 169, 0);
border: 0.2px solid #010101;
border-radius: 2.6px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0px 0px 0.9px #000000, 0px 0px 0px #0d0d0d;
border: 1.3px solid rgba(0, 0, 0, 0.7);
height: 16px;
width: 16px;
border-radius: 49px;
background: #ffffff;
cursor: pointer;
height: 8.4px;
}
input[type=range]:focus::-ms-fill-lower {
background: rgba(48, 113, 169, 0);
}
input[type=range]:focus::-ms-fill-upper {
background: rgba(54, 126, 189, 0);
}
.blue-background-class {
background-color: #C8EBFB;
}
.col {
padding-right: 0;
margin-right: 15px;
}
.selected {
background-color: #f9c7c8;
border: solid red 1px !important;
z-index: 1 !important;
}
.highlight {
background-color: #B7F8C7;
}

View File

@@ -0,0 +1,36 @@
{
"name": "bootstrap-rtl-ondemand",
"description": "Right-to-left (RTL) theme for Twitter Bootstrap 3.x activated with html dir=\"rtl\" attribute on-the-fly.",
"version": "3.3.4-ondemand",
"homepage": "https://github.com/bright/bootstrap-rtl",
"authors": [
"Morteza Ansarinia (https://github.com/morteza)",
"Michał Jastrzębowski (https://github.com/mjastrzebowski)",
"Adam Bar (https://github.com/NOtherDev)"
],
"main": [
"dist/css/bootstrap-rtl-ondemand.css"
],
"ignore": [
"**/.*",
"_config.yml",
"CNAME",
"composer.json",
"CONTRIBUTING.md",
"docs",
"js/tests"
],
"dependencies": {
"bootstrap": ">=3.3.0"
},
"license": "Unlicensed Public Domain",
"_release": "3.3.4-ondemand",
"_resolution": {
"type": "version",
"tag": "v3.3.4-ondemand",
"commit": "804fc517c3b45d88c11e8ed3e558878dc97f74c3"
},
"_source": "https://github.com/bright/bootstrap-rtl.git",
"_target": "^3.3.4-ondemand",
"_originalSource": "bootstrap-rtl-ondemand"
}

View File

@@ -0,0 +1,60 @@
module.exports = function(grunt) {
"use strict";
// Project configuration
grunt.initConfig({
// Read package.json Metadata.
pkg: grunt.file.readJSON('package.json'),
banner: '/*******************************************************************************\n' +
' * <%= pkg.name %> (version <%= pkg.version %>)\n' +
' * Author: <%= pkg.author %>\n' +
' * Created on: <%= grunt.template.today("mmmm dd,yyyy") %>\n' +
' * Project: <%= pkg.name %>\n' +
' * Copyright: Unlicensed Public Domain\n' +
' *******************************************************************************/\n',
less: {
rtl: {
options: {
strictMath: true,
cleancss: false,
sourceMap: true,
outputSourceFiles: true,
sourceMapURL: '<%= pkg.name %>.css.map',
sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map'
},
files: {
'dist/css/<%= pkg.name %>.css': 'less/bootstrap-rtl.less'
}
},
minify: {
options: {
cleancss: true
},
files: {
'dist/css/<%= pkg.name %>.min.css': 'dist/css/<%= pkg.name %>.css',
}
}
},
usebanner: {
options: {
position: 'top',
banner: '<%= banner %>',
linebreak: true
},
files: {
src: ['dist/css/<%= pkg.name %>.css',
'dist/css/<%= pkg.name %>.min.css']
}
}
});
// Load uglify plugin
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-banner');
// Default Task
grunt.registerTask('default', ['less', 'usebanner']);
};

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2011-2014 Twitter, Inc
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.

View File

@@ -0,0 +1,48 @@
# Bootstrap 3 with on-demand RTL support
---
This is a fork of [morteza's bootstrap-rtl](https://github.com/morteza/bootstrap-rtl/fork) theme. Contrary to the original, it doesn't override the default LTR direction and enforce RTL direction by default. It relies on `<html dir="ltr|rtl">` attribute and enables RTL direction only when `dir="rtl"` is set.
Bootstrap RTL provides simple yet robust right-to-left capability for Bootstrap 3, by employing new theming feature of it. Simply put its CSS after bootstrap's original CSS, to the pages designed by Bootstrap 3. It works just like an extension on top of the original Bootstrap:
```html
<!-- Original Bootstrap 3.x -->
<link rel="stylesheet" href="bootstrap.css">
<!-- Bootstrap RTL Theme -->
<link rel="stylesheet" href="bootstrap-rtl.css">
```
## Quick start
It's just like Bootstrap 3, nothing special. You can install it via bower:
* Run `bower install bootstrap-rtl-ondemand` and latest version will be installed under *bower_components/bootstrap-rtl/* directory.
In addition to bootstrap distribution, LESS codes for RTL theme and compiled CSS (`bootstrap-rtl.css`) are provided, as well as minified CSS (`bootstrap-rtl.min.css`). Check `dist/` directory for all the codes you need.
#### Auto Flip (`.flip`)
To automatically flip placements from right to left and vice versa (in bilingual pages), use `.flip` alongside `.pull-right` and `.pull-left`. This is a custom class and is not available in the original Bootstrap 3.
## Building CSS and JavaScript
Bootstrap RTL uses [Grunt](http://gruntjs.com/) for working with the framework. Follow these simple steps to prepare and compile:
1. Run `npm install` to download and prepare dependencies.
2. Run `grunt`, and check `dist/` directory for outputs.
## Author
**Morteza Ansarinia**
+ [https://github.com/morteza](https://github.com/morteza)
**Michał Jastrzębowski**
+ [https://github.com/mjastrzebowski](https://github.com/mjastrzebowski)

View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <http://unlicense.org/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

View File

@@ -0,0 +1,500 @@
/*
Holder - 2.2 - client side image placeholders
(c) 2012-2013 Ivan Malopinsky / http://imsky.co
Provided under the MIT License.
Commercial use requires attribution.
*/
var Holder = Holder || {};
(function (app, win) {
var preempted = false,
fallback = false,
canvas = document.createElement('canvas');
var dpr = 1, bsr = 1;
var resizable_images = [];
if (!canvas.getContext) {
fallback = true;
} else {
if (canvas.toDataURL("image/png")
.indexOf("data:image/png") < 0) {
//Android doesn't support data URI
fallback = true;
} else {
var ctx = canvas.getContext("2d");
}
}
if(!fallback){
dpr = window.devicePixelRatio || 1,
bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
}
var ratio = dpr / bsr;
var settings = {
domain: "holder.js",
images: "img",
bgnodes: ".holderjs",
themes: {
"gray": {
background: "#eee",
foreground: "#aaa",
size: 12
},
"social": {
background: "#3a5a97",
foreground: "#fff",
size: 12
},
"industrial": {
background: "#434A52",
foreground: "#C2F200",
size: 12
},
"sky": {
background: "#0D8FDB",
foreground: "#fff",
size: 12
},
"vine": {
background: "#39DBAC",
foreground: "#1E292C",
size: 12
},
"lava": {
background: "#F8591A",
foreground: "#1C2846",
size: 12
}
},
stylesheet: ""
};
app.flags = {
dimensions: {
regex: /^(\d+)x(\d+)$/,
output: function (val) {
var exec = this.regex.exec(val);
return {
width: +exec[1],
height: +exec[2]
}
}
},
fluid: {
regex: /^([0-9%]+)x([0-9%]+)$/,
output: function (val) {
var exec = this.regex.exec(val);
return {
width: exec[1],
height: exec[2]
}
}
},
colors: {
regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i,
output: function (val) {
var exec = this.regex.exec(val);
return {
size: settings.themes.gray.size,
foreground: "#" + exec[2],
background: "#" + exec[1]
}
}
},
text: {
regex: /text\:(.*)/,
output: function (val) {
return this.regex.exec(val)[1];
}
},
font: {
regex: /font\:(.*)/,
output: function (val) {
return this.regex.exec(val)[1];
}
},
auto: {
regex: /^auto$/
},
textmode: {
regex: /textmode\:(.*)/,
output: function(val){
return this.regex.exec(val)[1];
}
}
}
//getElementsByClassName polyfill
document.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll("."+e);if(t.evaluate){r=".//*[contains(concat(' ', @class, ' '), ' "+e+" ')]",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName("*"),r=new RegExp("(^|\\s)"+e+"(\\s|$)");for(i=0;i<n.length;i++)r.test(n[i].className)&&s.push(n[i])}return s})
//getComputedStyle polyfill
window.getComputedStyle||(window.getComputedStyle=function(e){return this.el=e,this.getPropertyValue=function(t){var n=/(\-([a-z]){1})/g;return t=="float"&&(t="styleFloat"),n.test(t)&&(t=t.replace(n,function(){return arguments[2].toUpperCase()})),e.currentStyle[t]?e.currentStyle[t]:null},this})
//http://javascript.nwbox.com/ContentLoaded by Diego Perini with modifications
function contentLoaded(n,t){var l="complete",s="readystatechange",u=!1,h=u,c=!0,i=n.document,a=i.documentElement,e=i.addEventListener?"addEventListener":"attachEvent",v=i.addEventListener?"removeEventListener":"detachEvent",f=i.addEventListener?"":"on",r=function(e){(e.type!=s||i.readyState==l)&&((e.type=="load"?n:i)[v](f+e.type,r,u),!h&&(h=!0)&&t.call(n,null))},o=function(){try{a.doScroll("left")}catch(n){setTimeout(o,50);return}r("poll")};if(i.readyState==l)t.call(n,"lazy");else{if(i.createEventObject&&a.doScroll){try{c=!n.frameElement}catch(y){}c&&o()}i[e](f+"DOMContentLoaded",r,u),i[e](f+s,r,u),n[e](f+"load",r,u)}}
//https://gist.github.com/991057 by Jed Schmidt with modifications
function selector(a){
a=a.match(/^(\W)?(.*)/);var b=document["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2]);
var ret=[]; b!==null&&(b.length?ret=b:b.length===0?ret=b:ret=[b]); return ret;
}
//shallow object property extend
function extend(a,b){
var c={};
for(var i in a){
if(a.hasOwnProperty(i)){
c[i]=a[i];
}
}
for(var i in b){
if(b.hasOwnProperty(i)){
c[i]=b[i];
}
}
return c
}
//hasOwnProperty polyfill
if (!Object.prototype.hasOwnProperty)
/*jshint -W001, -W103 */
Object.prototype.hasOwnProperty = function(prop) {
var proto = this.__proto__ || this.constructor.prototype;
return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
}
/*jshint +W001, +W103 */
function text_size(width, height, template) {
height = parseInt(height, 10);
width = parseInt(width, 10);
var bigSide = Math.max(height, width)
var smallSide = Math.min(height, width)
var scale = 1 / 12;
var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale);
return {
height: Math.round(Math.max(template.size, newHeight))
}
}
function draw(args) {
var ctx = args.ctx;
var dimensions = args.dimensions;
var template = args.template;
var ratio = args.ratio;
var holder = args.holder;
var literal = holder.textmode == "literal";
var exact = holder.textmode == "exact";
var ts = text_size(dimensions.width, dimensions.height, template);
var text_height = ts.height;
var width = dimensions.width * ratio,
height = dimensions.height * ratio;
var font = template.font ? template.font : "sans-serif";
canvas.width = width;
canvas.height = height;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = template.background;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = template.foreground;
ctx.font = "bold " + text_height + "px " + font;
var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
if (literal) {
var dimensions = holder.dimensions;
text = dimensions.width + "x" + dimensions.height;
}
else if(exact && holder.exact_dimensions){
var dimensions = holder.exact_dimensions;
text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
}
var text_width = ctx.measureText(text).width;
if (text_width / width >= 0.75) {
text_height = Math.floor(text_height * 0.75 * (width / text_width));
}
//Resetting font size if necessary
ctx.font = "bold " + (text_height * ratio) + "px " + font;
ctx.fillText(text, (width / 2), (height / 2), width);
return canvas.toDataURL("image/png");
}
function render(mode, el, holder, src) {
var dimensions = holder.dimensions,
theme = holder.theme,
text = holder.text ? decodeURIComponent(holder.text) : holder.text;
var dimensions_caption = dimensions.width + "x" + dimensions.height;
theme = (text ? extend(theme, {
text: text
}) : theme);
theme = (holder.font ? extend(theme, {
font: holder.font
}) : theme);
el.setAttribute("data-src", src);
holder.theme = theme;
el.holder_data = holder;
if (mode == "image") {
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
if (fallback || !holder.auto) {
el.style.width = dimensions.width + "px";
el.style.height = dimensions.height + "px";
}
if (fallback) {
el.style.backgroundColor = theme.background;
} else {
el.setAttribute("src", draw({ctx: ctx, dimensions: dimensions, template: theme, ratio:ratio, holder: holder}));
if(holder.textmode && holder.textmode == "exact"){
resizable_images.push(el);
resizable_update(el);
}
}
} else if (mode == "background") {
if (!fallback) {
el.style.backgroundImage = "url(" + draw({ctx:ctx, dimensions: dimensions, template: theme, ratio: ratio, holder: holder}) + ")";
el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px";
}
} else if (mode == "fluid") {
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
if (dimensions.height.slice(-1) == "%") {
el.style.height = dimensions.height
} else {
el.style.height = dimensions.height + "px"
}
if (dimensions.width.slice(-1) == "%") {
el.style.width = dimensions.width
} else {
el.style.width = dimensions.width + "px"
}
if (el.style.display == "inline" || el.style.display === "" || el.style.display == "none") {
el.style.display = "block";
}
if (fallback) {
el.style.backgroundColor = theme.background;
} else {
resizable_images.push(el);
resizable_update(el);
}
}
}
function dimension_check(el, callback) {
var dimensions = {
height: el.clientHeight,
width: el.clientWidth
};
if (!dimensions.height && !dimensions.width) {
if (el.hasAttribute("data-holder-invisible")) {
throw new Error("Holder: placeholder is not visible");
} else {
el.setAttribute("data-holder-invisible", true)
setTimeout(function () {
callback.call(this, el)
}, 1)
return null;
}
} else {
el.removeAttribute("data-holder-invisible")
}
return dimensions;
}
function resizable_update(element) {
var images;
if (element.nodeType == null) {
images = resizable_images;
} else {
images = [element]
}
for (var i in images) {
if (!images.hasOwnProperty(i)) {
continue;
}
var el = images[i]
if (el.holder_data) {
var holder = el.holder_data;
var dimensions = dimension_check(el, resizable_update)
if(dimensions){
if(holder.fluid){
el.setAttribute("src", draw({
ctx: ctx,
dimensions: dimensions,
template: holder.theme,
ratio: ratio,
holder: holder
}))
}
if(holder.textmode && holder.textmode == "exact"){
holder.exact_dimensions = dimensions;
el.setAttribute("src", draw({
ctx: ctx,
dimensions: holder.dimensions,
template: holder.theme,
ratio: ratio,
holder: holder
}))
}
}
}
}
}
function parse_flags(flags, options) {
var ret = {
theme: extend(settings.themes.gray, {})
};
var render = false;
for (sl = flags.length, j = 0; j < sl; j++) {
var flag = flags[j];
if (app.flags.dimensions.match(flag)) {
render = true;
ret.dimensions = app.flags.dimensions.output(flag);
} else if (app.flags.fluid.match(flag)) {
render = true;
ret.dimensions = app.flags.fluid.output(flag);
ret.fluid = true;
} else if (app.flags.textmode.match(flag)) {
ret.textmode = app.flags.textmode.output(flag)
} else if (app.flags.colors.match(flag)) {
ret.theme = app.flags.colors.output(flag);
} else if (options.themes[flag]) {
//If a theme is specified, it will override custom colors
if(options.themes.hasOwnProperty(flag)){
ret.theme = extend(options.themes[flag], {});
}
} else if (app.flags.font.match(flag)) {
ret.font = app.flags.font.output(flag);
} else if (app.flags.auto.match(flag)) {
ret.auto = true;
} else if (app.flags.text.match(flag)) {
ret.text = app.flags.text.output(flag);
}
}
return render ? ret : false;
}
for (var flag in app.flags) {
if (!app.flags.hasOwnProperty(flag)) continue;
app.flags[flag].match = function (val) {
return val.match(this.regex)
}
}
app.add_theme = function (name, theme) {
name != null && theme != null && (settings.themes[name] = theme);
return app;
};
app.add_image = function (src, el) {
var node = selector(el);
if (node.length) {
for (var i = 0, l = node.length; i < l; i++) {
var img = document.createElement("img")
img.setAttribute("data-src", src);
node[i].appendChild(img);
}
}
return app;
};
app.run = function (o) {
preempted = true;
var options = extend(settings, o),
images = [],
imageNodes = [],
bgnodes = [];
if (typeof (options.images) == "string") {
imageNodes = selector(options.images);
} else if (window.NodeList && options.images instanceof window.NodeList) {
imageNodes = options.images;
} else if (window.Node && options.images instanceof window.Node) {
imageNodes = [options.images];
}
if (typeof (options.bgnodes) == "string") {
bgnodes = selector(options.bgnodes);
} else if (window.NodeList && options.elements instanceof window.NodeList) {
bgnodes = options.bgnodes;
} else if (window.Node && options.bgnodes instanceof window.Node) {
bgnodes = [options.bgnodes];
}
for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]);
var holdercss = document.getElementById("holderjs-style");
if (!holdercss) {
holdercss = document.createElement("style");
holdercss.setAttribute("id", "holderjs-style");
holdercss.type = "text/css";
document.getElementsByTagName("head")[0].appendChild(holdercss);
}
if (!options.nocss) {
if (holdercss.styleSheet) {
holdercss.styleSheet.cssText += options.stylesheet;
} else {
holdercss.appendChild(document.createTextNode(options.stylesheet));
}
}
var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)");
for (var l = bgnodes.length, i = 0; i < l; i++) {
var src = window.getComputedStyle(bgnodes[i], null)
.getPropertyValue("background-image");
var flags = src.match(cssregex);
var bgsrc = bgnodes[i].getAttribute("data-background-src");
if (flags) {
var holder = parse_flags(flags[1].split("/"), options);
if (holder) {
render("background", bgnodes[i], holder, src);
}
} else if (bgsrc != null) {
var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1)
.split("/"), options);
if (holder) {
render("background", bgnodes[i], holder, src);
}
}
}
for (l = images.length, i = 0; i < l; i++) {
var attr_data_src, attr_src;
attr_src = attr_data_src = src = null;
try {
attr_src = images[i].getAttribute("src");
attr_datasrc = images[i].getAttribute("data-src");
} catch (e) {}
if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) {
src = attr_src;
} else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) {
src = attr_datasrc;
}
if (src) {
var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1)
.split("/"), options);
if (holder) {
if (holder.fluid) {
render("fluid", images[i], holder, src)
} else {
render("image", images[i], holder, src);
}
}
}
}
return app;
};
contentLoaded(win, function () {
if (window.addEventListener) {
window.addEventListener("resize", resizable_update, false);
window.addEventListener("orientationchange", resizable_update, false);
} else {
window.attachEvent("onresize", resizable_update)
}
preempted || app.run();
});
if (typeof define === "function" && define.amd) {
define([], function () {
return app;
});
}
})(Holder, window);

View File

@@ -0,0 +1,8 @@
/*
HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}</style>";
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/*! Respond.js v1.4.0: min/max-width media query polyfill * Copyright 2013 Scott Jehl
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
* */
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@.*keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]+\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);

View File

@@ -0,0 +1,27 @@
{
"name": "bootstrap-rtl-ondemand",
"description": "Right-to-left (RTL) theme for Twitter Bootstrap 3.x activated with html dir=\"rtl\" attribute on-the-fly.",
"version": "3.3.4-ondemand",
"homepage": "https://github.com/bright/bootstrap-rtl",
"authors": [
"Morteza Ansarinia (https://github.com/morteza)",
"Michał Jastrzębowski (https://github.com/mjastrzebowski)",
"Adam Bar (https://github.com/NOtherDev)"
],
"main": [
"dist/css/bootstrap-rtl-ondemand.css"
],
"ignore": [
"**/.*",
"_config.yml",
"CNAME",
"composer.json",
"CONTRIBUTING.md",
"docs",
"js/tests"
],
"dependencies": {
"bootstrap": ">=3.3.0"
},
"license": "Unlicensed Public Domain"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,500 @@
/*
Holder - 2.2 - client side image placeholders
(c) 2012-2013 Ivan Malopinsky / http://imsky.co
Provided under the MIT License.
Commercial use requires attribution.
*/
var Holder = Holder || {};
(function (app, win) {
var preempted = false,
fallback = false,
canvas = document.createElement('canvas');
var dpr = 1, bsr = 1;
var resizable_images = [];
if (!canvas.getContext) {
fallback = true;
} else {
if (canvas.toDataURL("image/png")
.indexOf("data:image/png") < 0) {
//Android doesn't support data URI
fallback = true;
} else {
var ctx = canvas.getContext("2d");
}
}
if(!fallback){
dpr = window.devicePixelRatio || 1,
bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
}
var ratio = dpr / bsr;
var settings = {
domain: "holder.js",
images: "img",
bgnodes: ".holderjs",
themes: {
"gray": {
background: "#eee",
foreground: "#aaa",
size: 12
},
"social": {
background: "#3a5a97",
foreground: "#fff",
size: 12
},
"industrial": {
background: "#434A52",
foreground: "#C2F200",
size: 12
},
"sky": {
background: "#0D8FDB",
foreground: "#fff",
size: 12
},
"vine": {
background: "#39DBAC",
foreground: "#1E292C",
size: 12
},
"lava": {
background: "#F8591A",
foreground: "#1C2846",
size: 12
}
},
stylesheet: ""
};
app.flags = {
dimensions: {
regex: /^(\d+)x(\d+)$/,
output: function (val) {
var exec = this.regex.exec(val);
return {
width: +exec[1],
height: +exec[2]
}
}
},
fluid: {
regex: /^([0-9%]+)x([0-9%]+)$/,
output: function (val) {
var exec = this.regex.exec(val);
return {
width: exec[1],
height: exec[2]
}
}
},
colors: {
regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i,
output: function (val) {
var exec = this.regex.exec(val);
return {
size: settings.themes.gray.size,
foreground: "#" + exec[2],
background: "#" + exec[1]
}
}
},
text: {
regex: /text\:(.*)/,
output: function (val) {
return this.regex.exec(val)[1];
}
},
font: {
regex: /font\:(.*)/,
output: function (val) {
return this.regex.exec(val)[1];
}
},
auto: {
regex: /^auto$/
},
textmode: {
regex: /textmode\:(.*)/,
output: function(val){
return this.regex.exec(val)[1];
}
}
}
//getElementsByClassName polyfill
document.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll("."+e);if(t.evaluate){r=".//*[contains(concat(' ', @class, ' '), ' "+e+" ')]",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName("*"),r=new RegExp("(^|\\s)"+e+"(\\s|$)");for(i=0;i<n.length;i++)r.test(n[i].className)&&s.push(n[i])}return s})
//getComputedStyle polyfill
window.getComputedStyle||(window.getComputedStyle=function(e){return this.el=e,this.getPropertyValue=function(t){var n=/(\-([a-z]){1})/g;return t=="float"&&(t="styleFloat"),n.test(t)&&(t=t.replace(n,function(){return arguments[2].toUpperCase()})),e.currentStyle[t]?e.currentStyle[t]:null},this})
//http://javascript.nwbox.com/ContentLoaded by Diego Perini with modifications
function contentLoaded(n,t){var l="complete",s="readystatechange",u=!1,h=u,c=!0,i=n.document,a=i.documentElement,e=i.addEventListener?"addEventListener":"attachEvent",v=i.addEventListener?"removeEventListener":"detachEvent",f=i.addEventListener?"":"on",r=function(e){(e.type!=s||i.readyState==l)&&((e.type=="load"?n:i)[v](f+e.type,r,u),!h&&(h=!0)&&t.call(n,null))},o=function(){try{a.doScroll("left")}catch(n){setTimeout(o,50);return}r("poll")};if(i.readyState==l)t.call(n,"lazy");else{if(i.createEventObject&&a.doScroll){try{c=!n.frameElement}catch(y){}c&&o()}i[e](f+"DOMContentLoaded",r,u),i[e](f+s,r,u),n[e](f+"load",r,u)}}
//https://gist.github.com/991057 by Jed Schmidt with modifications
function selector(a){
a=a.match(/^(\W)?(.*)/);var b=document["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2]);
var ret=[]; b!==null&&(b.length?ret=b:b.length===0?ret=b:ret=[b]); return ret;
}
//shallow object property extend
function extend(a,b){
var c={};
for(var i in a){
if(a.hasOwnProperty(i)){
c[i]=a[i];
}
}
for(var i in b){
if(b.hasOwnProperty(i)){
c[i]=b[i];
}
}
return c
}
//hasOwnProperty polyfill
if (!Object.prototype.hasOwnProperty)
/*jshint -W001, -W103 */
Object.prototype.hasOwnProperty = function(prop) {
var proto = this.__proto__ || this.constructor.prototype;
return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
}
/*jshint +W001, +W103 */
function text_size(width, height, template) {
height = parseInt(height, 10);
width = parseInt(width, 10);
var bigSide = Math.max(height, width)
var smallSide = Math.min(height, width)
var scale = 1 / 12;
var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale);
return {
height: Math.round(Math.max(template.size, newHeight))
}
}
function draw(args) {
var ctx = args.ctx;
var dimensions = args.dimensions;
var template = args.template;
var ratio = args.ratio;
var holder = args.holder;
var literal = holder.textmode == "literal";
var exact = holder.textmode == "exact";
var ts = text_size(dimensions.width, dimensions.height, template);
var text_height = ts.height;
var width = dimensions.width * ratio,
height = dimensions.height * ratio;
var font = template.font ? template.font : "sans-serif";
canvas.width = width;
canvas.height = height;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = template.background;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = template.foreground;
ctx.font = "bold " + text_height + "px " + font;
var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
if (literal) {
var dimensions = holder.dimensions;
text = dimensions.width + "x" + dimensions.height;
}
else if(exact && holder.exact_dimensions){
var dimensions = holder.exact_dimensions;
text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height));
}
var text_width = ctx.measureText(text).width;
if (text_width / width >= 0.75) {
text_height = Math.floor(text_height * 0.75 * (width / text_width));
}
//Resetting font size if necessary
ctx.font = "bold " + (text_height * ratio) + "px " + font;
ctx.fillText(text, (width / 2), (height / 2), width);
return canvas.toDataURL("image/png");
}
function render(mode, el, holder, src) {
var dimensions = holder.dimensions,
theme = holder.theme,
text = holder.text ? decodeURIComponent(holder.text) : holder.text;
var dimensions_caption = dimensions.width + "x" + dimensions.height;
theme = (text ? extend(theme, {
text: text
}) : theme);
theme = (holder.font ? extend(theme, {
font: holder.font
}) : theme);
el.setAttribute("data-src", src);
holder.theme = theme;
el.holder_data = holder;
if (mode == "image") {
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
if (fallback || !holder.auto) {
el.style.width = dimensions.width + "px";
el.style.height = dimensions.height + "px";
}
if (fallback) {
el.style.backgroundColor = theme.background;
} else {
el.setAttribute("src", draw({ctx: ctx, dimensions: dimensions, template: theme, ratio:ratio, holder: holder}));
if(holder.textmode && holder.textmode == "exact"){
resizable_images.push(el);
resizable_update(el);
}
}
} else if (mode == "background") {
if (!fallback) {
el.style.backgroundImage = "url(" + draw({ctx:ctx, dimensions: dimensions, template: theme, ratio: ratio, holder: holder}) + ")";
el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px";
}
} else if (mode == "fluid") {
el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption);
if (dimensions.height.slice(-1) == "%") {
el.style.height = dimensions.height
} else {
el.style.height = dimensions.height + "px"
}
if (dimensions.width.slice(-1) == "%") {
el.style.width = dimensions.width
} else {
el.style.width = dimensions.width + "px"
}
if (el.style.display == "inline" || el.style.display === "" || el.style.display == "none") {
el.style.display = "block";
}
if (fallback) {
el.style.backgroundColor = theme.background;
} else {
resizable_images.push(el);
resizable_update(el);
}
}
}
function dimension_check(el, callback) {
var dimensions = {
height: el.clientHeight,
width: el.clientWidth
};
if (!dimensions.height && !dimensions.width) {
if (el.hasAttribute("data-holder-invisible")) {
throw new Error("Holder: placeholder is not visible");
} else {
el.setAttribute("data-holder-invisible", true)
setTimeout(function () {
callback.call(this, el)
}, 1)
return null;
}
} else {
el.removeAttribute("data-holder-invisible")
}
return dimensions;
}
function resizable_update(element) {
var images;
if (element.nodeType == null) {
images = resizable_images;
} else {
images = [element]
}
for (var i in images) {
if (!images.hasOwnProperty(i)) {
continue;
}
var el = images[i]
if (el.holder_data) {
var holder = el.holder_data;
var dimensions = dimension_check(el, resizable_update)
if(dimensions){
if(holder.fluid){
el.setAttribute("src", draw({
ctx: ctx,
dimensions: dimensions,
template: holder.theme,
ratio: ratio,
holder: holder
}))
}
if(holder.textmode && holder.textmode == "exact"){
holder.exact_dimensions = dimensions;
el.setAttribute("src", draw({
ctx: ctx,
dimensions: holder.dimensions,
template: holder.theme,
ratio: ratio,
holder: holder
}))
}
}
}
}
}
function parse_flags(flags, options) {
var ret = {
theme: extend(settings.themes.gray, {})
};
var render = false;
for (sl = flags.length, j = 0; j < sl; j++) {
var flag = flags[j];
if (app.flags.dimensions.match(flag)) {
render = true;
ret.dimensions = app.flags.dimensions.output(flag);
} else if (app.flags.fluid.match(flag)) {
render = true;
ret.dimensions = app.flags.fluid.output(flag);
ret.fluid = true;
} else if (app.flags.textmode.match(flag)) {
ret.textmode = app.flags.textmode.output(flag)
} else if (app.flags.colors.match(flag)) {
ret.theme = app.flags.colors.output(flag);
} else if (options.themes[flag]) {
//If a theme is specified, it will override custom colors
if(options.themes.hasOwnProperty(flag)){
ret.theme = extend(options.themes[flag], {});
}
} else if (app.flags.font.match(flag)) {
ret.font = app.flags.font.output(flag);
} else if (app.flags.auto.match(flag)) {
ret.auto = true;
} else if (app.flags.text.match(flag)) {
ret.text = app.flags.text.output(flag);
}
}
return render ? ret : false;
}
for (var flag in app.flags) {
if (!app.flags.hasOwnProperty(flag)) continue;
app.flags[flag].match = function (val) {
return val.match(this.regex)
}
}
app.add_theme = function (name, theme) {
name != null && theme != null && (settings.themes[name] = theme);
return app;
};
app.add_image = function (src, el) {
var node = selector(el);
if (node.length) {
for (var i = 0, l = node.length; i < l; i++) {
var img = document.createElement("img")
img.setAttribute("data-src", src);
node[i].appendChild(img);
}
}
return app;
};
app.run = function (o) {
preempted = true;
var options = extend(settings, o),
images = [],
imageNodes = [],
bgnodes = [];
if (typeof (options.images) == "string") {
imageNodes = selector(options.images);
} else if (window.NodeList && options.images instanceof window.NodeList) {
imageNodes = options.images;
} else if (window.Node && options.images instanceof window.Node) {
imageNodes = [options.images];
}
if (typeof (options.bgnodes) == "string") {
bgnodes = selector(options.bgnodes);
} else if (window.NodeList && options.elements instanceof window.NodeList) {
bgnodes = options.bgnodes;
} else if (window.Node && options.bgnodes instanceof window.Node) {
bgnodes = [options.bgnodes];
}
for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]);
var holdercss = document.getElementById("holderjs-style");
if (!holdercss) {
holdercss = document.createElement("style");
holdercss.setAttribute("id", "holderjs-style");
holdercss.type = "text/css";
document.getElementsByTagName("head")[0].appendChild(holdercss);
}
if (!options.nocss) {
if (holdercss.styleSheet) {
holdercss.styleSheet.cssText += options.stylesheet;
} else {
holdercss.appendChild(document.createTextNode(options.stylesheet));
}
}
var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)");
for (var l = bgnodes.length, i = 0; i < l; i++) {
var src = window.getComputedStyle(bgnodes[i], null)
.getPropertyValue("background-image");
var flags = src.match(cssregex);
var bgsrc = bgnodes[i].getAttribute("data-background-src");
if (flags) {
var holder = parse_flags(flags[1].split("/"), options);
if (holder) {
render("background", bgnodes[i], holder, src);
}
} else if (bgsrc != null) {
var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1)
.split("/"), options);
if (holder) {
render("background", bgnodes[i], holder, src);
}
}
}
for (l = images.length, i = 0; i < l; i++) {
var attr_data_src, attr_src;
attr_src = attr_data_src = src = null;
try {
attr_src = images[i].getAttribute("src");
attr_datasrc = images[i].getAttribute("data-src");
} catch (e) {}
if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) {
src = attr_src;
} else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) {
src = attr_datasrc;
}
if (src) {
var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1)
.split("/"), options);
if (holder) {
if (holder.fluid) {
render("fluid", images[i], holder, src)
} else {
render("image", images[i], holder, src);
}
}
}
}
return app;
};
contentLoaded(win, function () {
if (window.addEventListener) {
window.addEventListener("resize", resizable_update, false);
window.addEventListener("orientationchange", resizable_update, false);
} else {
window.attachEvent("onresize", resizable_update)
}
preempted || app.run();
});
if (typeof define === "function" && define.amd) {
define([], function () {
return app;
});
}
})(Holder, window);

View File

@@ -0,0 +1,8 @@
/*
HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}</style>";
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/*! Respond.js v1.4.0: min/max-width media query polyfill * Copyright 2013 Scott Jehl
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
* */
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@.*keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]+\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);

View File

@@ -0,0 +1,20 @@
//
// RTL Alerts
// --------------------------------------------------
// Dismissable alerts
//
// Expand the left padding and account for the close button's positioning.
.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.
.alert-dismissible {
padding-left: (@alert-padding + 20);
padding-right: (@alert-padding);
// Adjust close link position
.close {
right: auto;
left: -21px;
}
}

View File

@@ -0,0 +1,21 @@
//
// RTL Badges
// --------------------------------------------------
// Base class
.badge {
.nav-pills > li > a > & {
margin-left: 0px;
margin-right: 3px;
}
.list-group-item > & {
float: left;
}
.list-group-item > & + & {
margin-left: 5px;
margin-right: auto;
}
}

View File

@@ -0,0 +1,59 @@
// --------------------------------------------------
// Right-to-Left (RTL) Theme for Bootstrap 3.x
// Morteza Ansarinia
// http://github.com/morteza/bootstrap-rtl
// --------------------------------------------------
// Core variables and mixins imported from the latest original bootstrap
@import "../bootstrap/less/variables.less";
@import "variables-rtl.less";
@import "mixins-rtl.less";
// Reset and dependencies
@import "normalize-rtl.less";
//@import "print.less";
//@import "glyphicons.less";
// Core CSS
@{rtl-prefix} {
//@import "scaffolding.less";
@import "type-rtl.less";
//@import "code.less";
@import "grid-rtl.less";
@import "tables-rtl.less";
@import "forms-rtl.less";
//@import "buttons.less";
// Components
//@import "component-animations.less";
@import "dropdowns-rtl.less";
@import "button-groups-rtl.less";
@import "input-groups-rtl.less";
@import "navs-rtl.less";
@import "navbar-rtl.less";
//@import "breadcrumbs.less";
@import "pagination-rtl.less";
@import "pager-rtl.less";
//@import "labels.less";
@import "badges-rtl.less";
//@import "jumbotron.less";
//@import "thumbnails.less";
@import "alerts-rtl.less";
@import "progress-bars-rtl.less";
@import "media-rtl.less";
@import "list-group-rtl.less";
@import "panels-rtl.less";
@import "responsive-embed-rtl.less";
//@import "wells.less";
@import "close-rtl.less";
// Components w/ JavaScript
@import "modals-rtl.less";
//@import "tooltip.less";
@import "popovers-rtl.less";
@import "carousel-rtl.less";
// Utility classes
@import "utilities-rtl.less";
//@import "responsive-utilities.less";
}

View File

@@ -0,0 +1,102 @@
//
// RTL Button groups
// --------------------------------------------------
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
> .btn {
float: right;
}
}
// Prevent double borders when buttons are next to each other
.btn-group {
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-right: -1px;
margin-left: 0px;
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
margin-right: -5px; // Offset the first child's margin
margin-left: 0px;
.btn-group,
.input-group {
float: right;
}
> .btn,
> .btn-group,
> .input-group {
margin-right: 5px;
margin-left: 0px;
}
}
// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
.btn-group > .btn:first-child {
margin-right: 0;
&:not(:last-child):not(.dropdown-toggle) {
border-top-right-radius: @border-radius-base;
border-bottom-right-radius: @border-radius-base;
.border-left-radius(0);
}
}
// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
.btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) {
border-top-left-radius: @border-radius-base;
border-bottom-left-radius: @border-radius-base;
.border-right-radius(0);
}
// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)
.btn-group > .btn-group {
float: right;
}
.btn-group.btn-group-justified > .btn,
.btn-group.btn-group-justified > .btn-group {
float: none;
}
.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group > .btn-group:first-child {
> .btn:last-child,
> .dropdown-toggle {
border-top-right-radius: @border-radius-base;
border-bottom-right-radius: @border-radius-base;
.border-left-radius(0);
}
}
.btn-group > .btn-group:last-child > .btn:first-child {
border-top-left-radius: @border-radius-base;
border-bottom-left-radius: @border-radius-base;
.border-right-radius(0);
}
// Reposition the caret
.btn .caret {
margin-right: 0;
}
// Vertical button groups
// ----------------------
.btn-group-vertical {
> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group {
margin-top: -1px;
margin-right: 0;
}
}

View File

@@ -0,0 +1,76 @@
//
// RTL Carousel
// --------------------------------------------------
// Left/right controls for nav
// ---------------------------
.carousel-control {
right: 0;
bottom: 0;
// Set gradients for backgrounds
&.left {
right: auto;
left: 0;
#gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));
}
&.right {
left: auto;
right: 0;
#gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));
}
.icon-prev,
.glyphicon-chevron-left {
left: 50%;
right: auto;
margin-right: -10px;
}
.icon-next,
.glyphicon-chevron-right {
right: 50%;
left: auto;
margin-left: -10px;
}
}
// Optional indicator pips
//
// Add an unordered list with the following class and add a list item for each
// slide your carousel holds.
.carousel-indicators {
right: 50%;
left: 0;
margin-right: -30%;
margin-left: 0;
padding-left: 0;
}
// Scale up controls for tablets and up
@media screen and (min-width: @screen-sm-min) {
// Scale up the controls a smidge
.carousel-control {
.glyphicon-chevron-left,
.icon-prev {
margin-left: 0;
margin-right: -15px;
}
.glyphicon-chevron-right,
.icon-next {
margin-left: 0;
margin-right: -15px;
}
}
// Show and left align the captions
.carousel-caption {
left: 20%;
right: 20%;
padding-bottom: 30px;
}
}

View File

@@ -0,0 +1,8 @@
//
// RTL Close icons
// --------------------------------------------------
.close {
float: left;
}

View File

@@ -0,0 +1,63 @@
//
// RTL Dropdown menus
// --------------------------------------------------
// Dropdown arrow/caret
.caret {
margin-right: 2px;
margin-left: 0;
}
// The dropdown menu (ul)
.dropdown-menu {
right: 0;
left: auto;
float: left;
text-align: right; // Ensures proper alignment if parent has it changed (e.g., modal footer)
// Aligns the dropdown menu to right
//
// Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`
&.pull-right {
left: 0;
right: auto;
float: right;
}
}
// Menu positioning
//
// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown
// menu with the parent.
.dropdown-menu-right {
left: auto; // Reset the default from `.dropdown-menu`
right: 0;
}
// With v3, we enabled auto-flipping if you have a dropdown within a right
// aligned nav component. To enable the undoing of that, we provide an override
// to restore the default dropdown menu alignment.
//
// This is only for left-aligning a dropdown menu within a `.navbar-right` or
// `.pull-right` nav component.
.dropdown-menu-left {
left: 0;
right: auto;
}
// Component alignment
//
// Reiterate per navbar.less and the modified component alignment there.
@media (min-width: @grid-float-breakpoint) {
.navbar-right {
.dropdown-menu {
.dropdown-menu-right();
}
// Necessary for overrides of the default right aligned menu.
// Will remove come v4 in all likelihood.
.dropdown-menu-left {
.dropdown-menu-left();
}
}
}

View File

@@ -0,0 +1,85 @@
// ---------------------------------------------
// Flipped classes
// ---------------------------------------------
// ---- Utilities ----
.pull-right {
float: left !important;
}
.pull-left {
float: right !important;
}
//TODO carousel
//TODO Glyphicons
// ---- Dropdown ----
.dropdown-menu-left {
left: auto;
right: 0;
}
// ---- Media ----
.media-right,
.media > .pull-right {
padding-right: 10px;
padding-left: initial;
}
.media-left,
.media > .pull-left {
padding-left: 10px;
padding-right: initial;
}
// ---- Navbar ----
@media (min-width: @grid-float-breakpoint) {
.navbar-left { .pull-left(); }
.navbar-right {
.pull-right();
margin-left: -@navbar-padding-horizontal;
margin-right: initial;
~ .navbar-right {
margin-left: 0;
margin-right: initial;
}
}
}
// ---- Tooltip ----
.tooltip {
&.top-left .tooltip-arrow {
left: @tooltip-arrow-width;
}
&.top-right .tooltip-arrow {
right: @tooltip-arrow-width;
}
&.right .tooltip-arrow {
right: 0;
border-left-color: @tooltip-arrow-color;
}
&.left .tooltip-arrow {
left: 0;
border-right-color: @tooltip-arrow-color;
}
&.bottom-left .tooltip-arrow {
left: @tooltip-arrow-width;
}
&.bottom-right .tooltip-arrow {
right: @tooltip-arrow-width;
}
}
// ---- Type ----
.text-left { text-align: right; }
.text-right { text-align: left; }
//DEPRECATED
blockquote.pull-right {
padding-left: 15px;
padding-right: 0;
border-left: 5px solid @blockquote-border-color;
border-right: 0;
text-align: left;
}

View File

@@ -0,0 +1,102 @@
//
// RTL Forms
// --------------------------------------------------
.radio,
.checkbox {
label {
padding-right: 20px;
padding-left: initial;
}
}
.radio input[type="radio"],
.radio-inline input[type="radio"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
margin-right: -20px;
margin-left: auto;
}
// Radios and checkboxes on same line
.radio-inline,
.checkbox-inline {
padding-right: 20px;
padding-left: 0;
}
.radio-inline + .radio-inline,
.checkbox-inline + .checkbox-inline {
margin-right: 10px; // space out consecutive inline controls
margin-left: 0;
}
.has-feedback {
// Ensure icons don't overlap text
.form-control {
padding-left: (@input-height-base * 1.25);
padding-right: 12px;
}
}
// Feedback icon (requires .glyphicon classes)
.form-control-feedback {
left: 0;
right: auto;
}
// Inline forms
//
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
// forms begin stacked on extra small (mobile) devices and then go inline when
// viewports reach <768px.
//
// Requires wrapping inputs and labels with `.form-group` for proper display of
// default HTML form controls and our custom form controls (e.g., input groups).
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
.form-inline {
// Kick in the inline
@media (min-width: @screen-sm-min) {
label {
padding-right: 0;
padding-left: initial;
}
.radio input[type="radio"],
.checkbox input[type="checkbox"] {
margin-right: 0;
margin-left: auto;
}
}
}
// Horizontal forms
//
// Horizontal forms are built on grid classes and allow you to create forms with
// labels on the left and inputs on the right.
.form-horizontal {
// Reset spacing and right align labels, but scope to media queries so that
// labels on narrow viewports stack the same as a default form example.
@media (min-width: @screen-sm-min) {
.control-label {
text-align: left;
}
}
// Validation states
//
// Reposition the icon because it's now within a grid column and columns have
// `position: relative;` on them. Also accounts for the grid gutter padding.
.has-feedback .form-control-feedback {
left: (@grid-gutter-width / 2);
right: auto;
}
}

View File

@@ -0,0 +1,45 @@
//
// RTL Grid system
// --------------------------------------------------
// Columns
//
// Common styles for small and large grid columns
.make-rtl-grid-columns(@rtl-prefix);
// Extra small grid
//
// Columns, offsets, pushes, and pulls for extra small devices like
// smartphones.
.make-rtl-grid(xs, @rtl-prefix);
// Small grid
//
// Columns, offsets, pushes, and pulls for the small device range, from phones
// to tablets.
@media (min-width: @screen-sm-min) {
.make-rtl-grid(sm, @rtl-prefix);
}
// Medium grid
//
// Columns, offsets, pushes, and pulls for the desktop device range.
@media (min-width: @screen-md-min) {
.make-rtl-grid(md, @rtl-prefix);
}
// Large grid
//
// Columns, offsets, pushes, and pulls for the large desktop device range.
@media (min-width: @screen-lg-min) {
.make-rtl-grid(lg, @rtl-prefix);
}

View File

@@ -0,0 +1,76 @@
//
// Input groups
// --------------------------------------------------
// Base styles
// -------------------------
.input-group {
.form-control {
// IE9 fubars the placeholder attribute in text inputs and the arrows on
// select elements in input groups. To fix it, we float the input. Details:
// https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855
float: right;
}
}
// Reset rounded corners
.input-group .form-control:first-child,
.input-group-addon:first-child,
.input-group-btn:first-child > .btn,
.input-group-btn:first-child > .btn-group > .btn,
.input-group-btn:first-child > .dropdown-toggle,
.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
.border-right-radius(@border-radius-base);
.border-left-radius(0);
}
.input-group-addon:first-child {
border-left: 0px;
border-right: 1px solid;
}
.input-group .form-control:last-child,
.input-group-addon:last-child,
.input-group-btn:last-child > .btn,
.input-group-btn:last-child > .btn-group > .btn,
.input-group-btn:last-child > .dropdown-toggle,
.input-group-btn:first-child > .btn:not(:first-child),
.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
.border-left-radius(@border-radius-base);
.border-right-radius(0);
}
.input-group-addon:last-child {
border-left-width: 1px;
border-left-style: solid;
border-right: 0px;
}
// Button input groups
// -------------------------
.input-group-btn {
// Negative margin for spacing, position for bringing hovered/focused/actived
// element above the siblings.
> .btn {
+ .btn {
margin-right: -1px;
margin-left: auto;
}
}
// Negative margin to only have a 1px border between the two
&:first-child {
> .btn,
> .btn-group {
margin-left: -1px;
margin-right: auto;
}
}
&:last-child {
> .btn,
> .btn-group {
margin-right: -1px;
margin-left: auto;
}
}
}

View File

@@ -0,0 +1,14 @@
//
// List groups
// --------------------------------------------------
// Base class
//
// Easily usable on <ul>, <ol>, or <div>.
.list-group {
padding-right: 0; // reset padding because ul and ol
padding-left: initial;
}

View File

@@ -0,0 +1,47 @@
// RTL Media objects
// --------------------------------------------------
// Media image alignment
// -------------------------
.media {
> .pull-left {
margin-right: 10px;
&.flip {
margin-right: 0;
margin-left: 10px;
}
}
> .pull-right {
margin-left: 10px;
&.flip {
margin-left: 0;
margin-right: 10px;
}
}
}
.media-right,
.media > .pull-right {
padding-right: 10px;
padding-left: initial;
}
.media-left,
.media > .pull-left {
padding-left: 10px;
padding-right: initial;
}
// Media list variation
// -------------------------
// Undo default ul/ol styles
.media-list {
padding-right: 0;
padding-left: initial;
list-style: none;
}

View File

@@ -0,0 +1,39 @@
// Mixins
// --------------------------------------------------
// Utilities
@import "../bootstrap/less/mixins/hide-text.less";
@import "../bootstrap/less/mixins/opacity.less";
@import "../bootstrap/less/mixins/image.less";
@import "../bootstrap/less/mixins/labels.less";
@import "../bootstrap/less/mixins/reset-filter.less";
@import "../bootstrap/less/mixins/resize.less";
@import "../bootstrap/less/mixins/responsive-visibility.less";
@import "../bootstrap/less/mixins/size.less";
@import "../bootstrap/less/mixins/tab-focus.less";
@import "../bootstrap/less/mixins/text-emphasis.less";
@import "../bootstrap/less/mixins/text-overflow.less";
@import "../bootstrap/less/mixins/vendor-prefixes.less";
// Components
@import "../bootstrap/less/mixins/alerts.less";
@import "../bootstrap/less/mixins/buttons.less";
@import "../bootstrap/less/mixins/panels.less";
@import "mixins/pagination-rtl.less"; // RTL
@import "../bootstrap/less/mixins/list-group.less";
@import "../bootstrap/less/mixins/nav-divider.less";
@import "../bootstrap/less/mixins/forms.less";
@import "../bootstrap/less/mixins/progress-bar.less";
@import "../bootstrap/less/mixins/table-row.less";
// Skins
@import "../bootstrap/less/mixins/background-variant.less";
@import "mixins/border-radius-flipped.less"; //FLIPPED
@import "mixins/gradients-rtl.less"; // RTL
// Layout
@import "../bootstrap/less/mixins/clearfix.less";
@import "../bootstrap/less/mixins/center-block.less";
@import "../bootstrap/less/mixins/nav-vertical-align.less";
@import "mixins/grid-framework-rtl.less"; // RTL
@import "mixins/grid-rtl.less"; // RTL

View File

@@ -0,0 +1,39 @@
// Mixins
// --------------------------------------------------
// Utilities
@import "../bootstrap/less/mixins/hide-text.less";
@import "../bootstrap/less/mixins/opacity.less";
@import "../bootstrap/less/mixins/image.less";
@import "../bootstrap/less/mixins/labels.less";
@import "../bootstrap/less/mixins/reset-filter.less";
@import "../bootstrap/less/mixins/resize.less";
@import "../bootstrap/less/mixins/responsive-visibility.less";
@import "../bootstrap/less/mixins/size.less";
@import "../bootstrap/less/mixins/tab-focus.less";
@import "../bootstrap/less/mixins/text-emphasis.less";
@import "../bootstrap/less/mixins/text-overflow.less";
@import "../bootstrap/less/mixins/vendor-prefixes.less";
// Components
@import "../bootstrap/less/mixins/alerts.less";
@import "../bootstrap/less/mixins/buttons.less";
@import "../bootstrap/less/mixins/panels.less";
@import "mixins/pagination-rtl.less"; // RTL
@import "../bootstrap/less/mixins/list-group.less";
@import "../bootstrap/less/mixins/nav-divider.less";
@import "../bootstrap/less/mixins/forms.less";
@import "../bootstrap/less/mixins/progress-bar.less";
@import "../bootstrap/less/mixins/table-row.less";
// Skins
@import "../bootstrap/less/mixins/background-variant.less";
@import "../bootstrap/less/mixins/border-radius.less";
@import "mixins/gradients-rtl.less"; // RTL
// Layout
@import "../bootstrap/less/mixins/clearfix.less";
@import "../bootstrap/less/mixins/center-block.less";
@import "../bootstrap/less/mixins/nav-vertical-align.less";
@import "mixins/grid-framework-rtl.less"; // RTL
@import "mixins/grid-rtl.less"; // RTL

Some files were not shown because too many files have changed in this diff Show More