Merge branch 'release-1.0.0'
@ -1,9 +1,28 @@
|
||||
X-editable changelog
|
||||
=============================
|
||||
|
||||
Version 1.0.0 wip
|
||||
Version 1.0.0 Nov 19, 2012
|
||||
----------------------------
|
||||
Initial release. Based on bootstrap-editable 1.1.4, but strongly refactored.
|
||||
- support of bootstrap, jqueryui or pure jquery as core library
|
||||
- directory structure re-arranged: split on several js files
|
||||
- all known bugs of bootstrap-editable closed
|
||||
Initial release. This library is new life of bootstrap-editable (1.1.4) that was strongly refactored and improved.
|
||||
Main features:
|
||||
- support not only bootstrap but any core library: bootstrap, jquery-ui or pure jquery
|
||||
- different container classes to show form: popover, tooltip, poshytip, etc
|
||||
- inline and popup versions
|
||||
- new directory structure and logic in separate js files allowing easy contribution
|
||||
|
||||
It is not fully compatible with bootstrap-editable but has mainly the same interface and api.
|
||||
Here list of differences to help you to upgrade your application:
|
||||
|
||||
[change] 'toggle' option value can be only click|manual (not toggling element id). In case of 'manual' you should write handler calling 'show' method.
|
||||
[change] 'validate' option cannot be defined as object anymore.
|
||||
[change] events 'init', 'update', 'shown', 'hidden' removed. Events 'save', 'cancel' added. Event 'render' remains.
|
||||
[change] input's optiom 'template' renamed to 'tpl' (to exclude conflict with container's template).
|
||||
[change] value can be stored internaly as object (previously was always string). Usefull for date inupt.
|
||||
[change] 'error' callback option is removed. 'success' callback remained.
|
||||
[enh] 'source' option in select can be array of structure [{value: 1, text: 'abc'}, {...}]. This allows to keep ordering of items in dropdown list. Previous format is supported for compability.
|
||||
[enh] api method 'setValue' to set manually value of editable.
|
||||
[change] locales directory is excluded from bootstrap-datepicker input. If you need localization you should jus download corresponding file from github.
|
||||
[change] date and dateui specific options can be set only via 'datepicker' option in first level of config (previously it was possible to set some options directly in config, e.g. weekStart).
|
||||
[change] if 'url' option defined as function - it is used as submit method instead of ajax (previously it was dynamically return url string and ajax occured anyway)
|
||||
|
||||
Also all known bugs of bootstrap-editable were closed.
|
278
LICENSE-GPL
@ -1,278 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
@ -3,14 +3,14 @@
|
||||
In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery.
|
||||
|
||||
## Description
|
||||
X-editable is new life of [bootstrap-editable](http://github.com/vitalets/bootstrap-editable) that was strongly refactored and extended.
|
||||
X-editable is new life of [bootstrap-editable](http://github.com/vitalets/bootstrap-editable) that was strongly refactored and improved.
|
||||
|
||||
## Demo & Documentation
|
||||
|
||||
**http://vitalets.github.com/x-editable**
|
||||
|
||||
## Contributing
|
||||
Please make all pull requests against `dev` branch. Thanks!
|
||||
Please make all pull requests against `dev` branch. Thanks for your support!
|
||||
|
||||
### Important notes
|
||||
Please don't edit files in the `dist` subdirectory as they are generated via grunt. You'll find source code in the `src` subdirectory!
|
||||
@ -40,4 +40,4 @@ Note that the `phantomjs` executable needs to be in the system `PATH` for grunt
|
||||
|
||||
## License
|
||||
Copyright (c) 2012 Vitaliy Potapov
|
||||
Licensed under the MIT, GPL licenses.
|
||||
Licensed under the MIT licenses.
|
||||
|
215
grunt.js
@ -1,43 +1,37 @@
|
||||
/*global module:false*/
|
||||
module.exports = function(grunt) {
|
||||
function getFiles() {
|
||||
//directories
|
||||
var
|
||||
lib = 'src/',
|
||||
forms = lib+'editable-form/',
|
||||
inputs = lib+'inputs/',
|
||||
containers = lib+'containers/';
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib');
|
||||
|
||||
//grunt.loadTasks('tasks/');
|
||||
//config for different cores of lib
|
||||
var config = {
|
||||
bootstrap: {
|
||||
form: [forms+'editable-form-bootstrap.js'],
|
||||
container: [containers+'editable-popover.js'],
|
||||
inputs: [inputs+'date/date.js', inputs+'date/bootstrap-datepicker/js/bootstrap-datepicker.js'],
|
||||
css: [inputs+'date/bootstrap-datepicker/css/datepicker.css']
|
||||
},
|
||||
jqueryui: {
|
||||
form: [forms+'editable-form-jqueryui.js'],
|
||||
container: [containers+'editable-tooltip.js'],
|
||||
inputs: [inputs+'dateui/dateui.js'],
|
||||
css: []
|
||||
},
|
||||
jquery: {
|
||||
form: [],
|
||||
container: [containers+'editable-poshytip.js'],
|
||||
inputs: [inputs+'dateui/dateui.js'],
|
||||
css: []
|
||||
}
|
||||
};
|
||||
|
||||
//directories
|
||||
var
|
||||
lib = 'src/',
|
||||
forms = lib+'editable-form/',
|
||||
inputs = lib+'inputs/',
|
||||
containers = lib+'containers/';
|
||||
|
||||
//config for different cores of lib
|
||||
var config = {
|
||||
bootstrap: {
|
||||
form: [forms+'editable-form-bootstrap.js'],
|
||||
container: [containers+'editable-popover.js'],
|
||||
inputs: [inputs+'date/date.js', inputs+'date/bootstrap-datepicker.js'],
|
||||
css: [inputs+'date/datepicker.css']
|
||||
},
|
||||
jqueryui: {
|
||||
form: [forms+'editable-form-jqueryui.js'],
|
||||
container: [containers+'editable-tooltip.js'],
|
||||
inputs: [inputs+'dateui.js'],
|
||||
css: []
|
||||
},
|
||||
jquery: {
|
||||
form: [],
|
||||
container: [containers+'editable-poshytip.js'],
|
||||
inputs: [inputs+'dateui.js'],
|
||||
css: []
|
||||
}
|
||||
};
|
||||
|
||||
var inline = [containers+'editable-inline.js'];
|
||||
|
||||
//common js files
|
||||
var js = [
|
||||
var inline = [containers+'editable-inline.js'];
|
||||
|
||||
//common js files
|
||||
var js = [
|
||||
'<banner:meta.banner>',
|
||||
forms+'editable-form.js',
|
||||
forms+'editable-form-utils.js',
|
||||
@ -47,59 +41,71 @@ containers = lib+'containers/';
|
||||
inputs+'text.js',
|
||||
inputs+'textarea.js',
|
||||
inputs+'select.js'
|
||||
];
|
||||
|
||||
//common css files
|
||||
var css = [
|
||||
];
|
||||
|
||||
//common css files
|
||||
var css = [
|
||||
'<banner:meta.banner>',
|
||||
forms+'editable-form.css',
|
||||
containers+'editable-container.css',
|
||||
lib+'element/editable-element.css'
|
||||
];
|
||||
|
||||
//create grunt concat task
|
||||
var task, folder, dest, concat_files = {}, min_files = {};
|
||||
for(var k in config) {
|
||||
folder = '<%= dist %>/'+k+'-editable/';
|
||||
];
|
||||
|
||||
//popup
|
||||
task = k+'_popup_js';
|
||||
dest = folder+'js/'+k+'-editable'+ (k === 'jquery' ? '-poshytip' : '');
|
||||
concat_files[task] = {
|
||||
src: js.concat(config[k].form).concat(config[k].container).concat(config[k].inputs),
|
||||
dest: dest+'.js'
|
||||
};
|
||||
min_files[task] = {
|
||||
src: ['<banner:meta.banner>', '<config:concat.'+task+'.dest>'],
|
||||
dest: dest + '.min.js'
|
||||
};
|
||||
|
||||
//inline
|
||||
task = k+'_inline_js';
|
||||
dest = folder+'js/'+k+'-editable-inline';
|
||||
concat_files[task] = {
|
||||
src: js.concat(config[k].form).concat(inline).concat(config[k].inputs),
|
||||
dest: dest+'.js'
|
||||
};
|
||||
min_files[task] = {
|
||||
src: ['<banner:meta.banner>', '<config:concat.'+task+'.dest>'],
|
||||
dest: dest + '.min.js'
|
||||
};
|
||||
//create 'concat' config
|
||||
var task, folder, dest, concat_files = {}, min_files = {};
|
||||
for(var k in config) {
|
||||
folder = '<%= dist %>/'+k+'-editable/';
|
||||
|
||||
//css
|
||||
concat_files[k+'_css'] = {
|
||||
src: css.concat(config[k].css),
|
||||
dest: folder+'css/'+k+'-editable.css'
|
||||
};
|
||||
}
|
||||
//popup
|
||||
task = k+'_popup_js';
|
||||
dest = folder+'js/'+k+'-editable'+ (k === 'jquery' ? '-poshytip' : '');
|
||||
concat_files[task] = {
|
||||
src: js.concat(config[k].form).concat(config[k].container).concat(config[k].inputs),
|
||||
dest: dest+'.js'
|
||||
};
|
||||
min_files[task] = {
|
||||
src: ['<banner:meta.banner>', '<config:concat.'+task+'.dest>'],
|
||||
dest: dest + '.min.js'
|
||||
};
|
||||
|
||||
//inline
|
||||
task = k+'_inline_js';
|
||||
dest = folder+'js/'+k+'-editable-inline';
|
||||
concat_files[task] = {
|
||||
src: js.concat(config[k].form).concat(inline).concat(config[k].inputs),
|
||||
dest: dest+'.js'
|
||||
};
|
||||
min_files[task] = {
|
||||
src: ['<banner:meta.banner>', '<config:concat.'+task+'.dest>'],
|
||||
dest: dest + '.min.js'
|
||||
};
|
||||
|
||||
//css
|
||||
concat_files[k+'_css'] = {
|
||||
src: css.concat(config[k].css),
|
||||
dest: folder+'css/'+k+'-editable.css'
|
||||
};
|
||||
}
|
||||
|
||||
return {concat_files: concat_files, min_files: min_files};
|
||||
|
||||
}
|
||||
|
||||
/*global module:false*/
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib');
|
||||
|
||||
//module for testing
|
||||
var module = '';
|
||||
//module = '&module=textarea';
|
||||
//module = '&module=select';
|
||||
//module = '&module=text';
|
||||
|
||||
//get js and css for different builds
|
||||
var files = getFiles();
|
||||
|
||||
|
||||
// Project configuration.
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: '<json:package.json>',
|
||||
dist: 'dist',
|
||||
@ -111,8 +117,8 @@ containers = lib+'containers/';
|
||||
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
|
||||
},
|
||||
clean: ['<config:dist>'],
|
||||
concat: concat_files,
|
||||
min: min_files,
|
||||
concat: files.concat_files,
|
||||
min: files.min_files,
|
||||
qunit: {
|
||||
bootstrap: [
|
||||
'http://localhost:8000/test/index.html?f=bootstrap&c=popup'+module,
|
||||
@ -142,8 +148,8 @@ containers = lib+'containers/';
|
||||
'src/inputs/*.js',
|
||||
'src/element/*.js',
|
||||
'src/inputs/*.js',
|
||||
'src/inputs/date/date.js'
|
||||
//do not check bootstrap-datepicker
|
||||
'src/inputs/date/date.js',
|
||||
'src/inputs/dateui/dateui.js'
|
||||
]
|
||||
},
|
||||
/*
|
||||
@ -174,17 +180,41 @@ containers = lib+'containers/';
|
||||
copy: {
|
||||
dist: {
|
||||
files: {
|
||||
'<%= dist %>/bootstrap-editable/css/img' : 'src/editable-form/img/*',
|
||||
'<%= dist %>/jqueryui-editable/css/img' : 'src/editable-form/img/*',
|
||||
'<%= dist %>/jquery-editable/css/img' : 'src/editable-form/img/*',
|
||||
'<%= dist %>/bootstrap-editable/js/locales' : 'src/inputs/date/locales/*',
|
||||
'<%= dist %>': ['LICENSE-GPL', 'LICENSE-MIT', 'README.md', 'CHANGELOG.txt']
|
||||
'<%= dist %>/bootstrap-editable/css/img/' : 'src/editable-form/img/*',
|
||||
'<%= dist %>/jqueryui-editable/css/img/' : 'src/editable-form/img/*',
|
||||
'<%= dist %>/jquery-editable/css/img/' : 'src/editable-form/img/*',
|
||||
//licences
|
||||
'<%= dist %>/': ['LICENSE-MIT', 'README.md', 'CHANGELOG.txt']
|
||||
},
|
||||
options: {
|
||||
flatten: true
|
||||
}
|
||||
}
|
||||
},
|
||||
ui_datepicker: {
|
||||
files: {
|
||||
//copy jquery ui datepicker
|
||||
'<%= dist %>/jquery-editable/jquery-ui-datepicker/' : 'src/inputs/dateui/jquery-ui-datepicker/**'
|
||||
}
|
||||
}
|
||||
},
|
||||
yuidoc: {
|
||||
compile: {
|
||||
name: '<%= pkg.title || pkg.name %>',
|
||||
description: '<%= pkg.description %>',
|
||||
version: '<%= pkg.version %>',
|
||||
url: "<%= pkg.homepage %>",
|
||||
// logo: 'src/editable-form/img/loading.gif',
|
||||
options: {
|
||||
paths: "src/",
|
||||
ignorePaths: ['src/inputs/date/locales'],
|
||||
outdir: "../docs/",
|
||||
// theme: "simple",
|
||||
themedir: "../yuidoc-theme"
|
||||
//themedir: "../yuidoc-bootstrap-theme-master"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//compress does not work properly for MAC OS (see https://github.com/vitalets/bootstrap-editable/issues/19)
|
||||
//zip will be created manually
|
||||
/*
|
||||
@ -214,15 +244,16 @@ containers = lib+'containers/';
|
||||
});
|
||||
|
||||
//test task
|
||||
grunt.registerTask('test', 'server qunit:bootstrap');
|
||||
grunt.registerTask('testall', 'server qunit');
|
||||
grunt.registerTask('test', 'lint server qunit:bootstrap');
|
||||
grunt.registerTask('testall', 'lint server qunit');
|
||||
|
||||
// Default task.
|
||||
// grunt.registerTask('default', 'lint qunit');
|
||||
grunt.registerTask('default', 'clean concat min copy');
|
||||
grunt.registerTask('default', 'clean lint concat min copy');
|
||||
|
||||
// build
|
||||
grunt.registerTask('build', 'clean lint concat min copy');
|
||||
|
||||
//to run particular task use ":", e.g. copy:libs
|
||||
};
|
||||
|
||||
|
9440
libs/jquery-ui-datepicker/js/jquery-1.8.2.js
vendored
@ -1,470 +0,0 @@
|
||||
/*
|
||||
* Poshy Tip jQuery plugin v1.1
|
||||
* http://vadikom.com/tools/poshy-tip-jquery-plugin-for-stylish-tooltips/
|
||||
* Copyright 2010-2011, Vasil Dinkov, http://vadikom.com/
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var tips = [],
|
||||
reBgImage = /^url\(["']?([^"'\)]*)["']?\);?$/i,
|
||||
rePNG = /\.png$/i,
|
||||
ie6 = $.browser.msie && $.browser.version == 6;
|
||||
|
||||
// make sure the tips' position is updated on resize
|
||||
function handleWindowResize() {
|
||||
$.each(tips, function() {
|
||||
this.refresh(true);
|
||||
});
|
||||
}
|
||||
$(window).resize(handleWindowResize);
|
||||
|
||||
$.Poshytip = function(elm, options) {
|
||||
this.$elm = $(elm);
|
||||
this.opts = $.extend({}, $.fn.poshytip.defaults, options);
|
||||
this.$tip = $(['<div class="',this.opts.className,'">',
|
||||
'<div class="tip-inner tip-bg-image"></div>',
|
||||
'<div class="tip-arrow tip-arrow-top tip-arrow-right tip-arrow-bottom tip-arrow-left"></div>',
|
||||
'</div>'].join('')).appendTo(document.body);
|
||||
this.$arrow = this.$tip.find('div.tip-arrow');
|
||||
this.$inner = this.$tip.find('div.tip-inner');
|
||||
this.disabled = false;
|
||||
this.content = null;
|
||||
this.init();
|
||||
};
|
||||
|
||||
$.Poshytip.prototype = {
|
||||
init: function() {
|
||||
tips.push(this);
|
||||
|
||||
// save the original title and a reference to the Poshytip object
|
||||
var title = this.$elm.attr('title');
|
||||
this.$elm.data('title.poshytip', title !== undefined ? title : null)
|
||||
.data('poshytip', this);
|
||||
|
||||
// hook element events
|
||||
if (this.opts.showOn != 'none') {
|
||||
this.$elm.bind({
|
||||
'mouseenter.poshytip': $.proxy(this.mouseenter, this),
|
||||
'mouseleave.poshytip': $.proxy(this.mouseleave, this)
|
||||
});
|
||||
switch (this.opts.showOn) {
|
||||
case 'hover':
|
||||
if (this.opts.alignTo == 'cursor')
|
||||
this.$elm.bind('mousemove.poshytip', $.proxy(this.mousemove, this));
|
||||
if (this.opts.allowTipHover)
|
||||
this.$tip.hover($.proxy(this.clearTimeouts, this), $.proxy(this.mouseleave, this));
|
||||
break;
|
||||
case 'focus':
|
||||
this.$elm.bind({
|
||||
'focus.poshytip': $.proxy(this.show, this),
|
||||
'blur.poshytip': $.proxy(this.hide, this)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
mouseenter: function(e) {
|
||||
if (this.disabled)
|
||||
return true;
|
||||
|
||||
this.$elm.attr('title', '');
|
||||
if (this.opts.showOn == 'focus')
|
||||
return true;
|
||||
|
||||
this.clearTimeouts();
|
||||
this.showTimeout = setTimeout($.proxy(this.show, this), this.opts.showTimeout);
|
||||
},
|
||||
mouseleave: function(e) {
|
||||
if (this.disabled || this.asyncAnimating && (this.$tip[0] === e.relatedTarget || jQuery.contains(this.$tip[0], e.relatedTarget)))
|
||||
return true;
|
||||
|
||||
var title = this.$elm.data('title.poshytip');
|
||||
if (title !== null)
|
||||
this.$elm.attr('title', title);
|
||||
if (this.opts.showOn == 'focus')
|
||||
return true;
|
||||
|
||||
this.clearTimeouts();
|
||||
this.hideTimeout = setTimeout($.proxy(this.hide, this), this.opts.hideTimeout);
|
||||
},
|
||||
mousemove: function(e) {
|
||||
if (this.disabled)
|
||||
return true;
|
||||
|
||||
this.eventX = e.pageX;
|
||||
this.eventY = e.pageY;
|
||||
if (this.opts.followCursor && this.$tip.data('active')) {
|
||||
this.calcPos();
|
||||
this.$tip.css({left: this.pos.l, top: this.pos.t});
|
||||
if (this.pos.arrow)
|
||||
this.$arrow[0].className = 'tip-arrow tip-arrow-' + this.pos.arrow;
|
||||
}
|
||||
},
|
||||
show: function() {
|
||||
if (this.disabled || this.$tip.data('active'))
|
||||
return;
|
||||
|
||||
this.reset();
|
||||
this.update();
|
||||
this.display();
|
||||
if (this.opts.timeOnScreen)
|
||||
setTimeout($.proxy(this.hide, this), this.opts.timeOnScreen);
|
||||
},
|
||||
hide: function() {
|
||||
if (this.disabled || !this.$tip.data('active'))
|
||||
return;
|
||||
|
||||
this.display(true);
|
||||
},
|
||||
reset: function() {
|
||||
this.$tip.queue([]).detach().css('visibility', 'hidden').data('active', false);
|
||||
this.$inner.find('*').poshytip('hide');
|
||||
if (this.opts.fade)
|
||||
this.$tip.css('opacity', this.opacity);
|
||||
this.$arrow[0].className = 'tip-arrow tip-arrow-top tip-arrow-right tip-arrow-bottom tip-arrow-left';
|
||||
this.asyncAnimating = false;
|
||||
},
|
||||
update: function(content, dontOverwriteOption) {
|
||||
if (this.disabled)
|
||||
return;
|
||||
|
||||
var async = content !== undefined;
|
||||
if (async) {
|
||||
if (!dontOverwriteOption)
|
||||
this.opts.content = content;
|
||||
if (!this.$tip.data('active'))
|
||||
return;
|
||||
} else {
|
||||
content = this.opts.content;
|
||||
}
|
||||
|
||||
// update content only if it has been changed since last time
|
||||
var self = this,
|
||||
newContent = typeof content == 'function' ?
|
||||
content.call(this.$elm[0], function(newContent) {
|
||||
self.update(newContent);
|
||||
}) :
|
||||
content == '[title]' ? this.$elm.data('title.poshytip') : content;
|
||||
if (this.content !== newContent) {
|
||||
this.$inner.empty().append(newContent);
|
||||
this.content = newContent;
|
||||
}
|
||||
|
||||
this.refresh(async);
|
||||
},
|
||||
refresh: function(async) {
|
||||
if (this.disabled)
|
||||
return;
|
||||
|
||||
if (async) {
|
||||
if (!this.$tip.data('active'))
|
||||
return;
|
||||
// save current position as we will need to animate
|
||||
var currPos = {left: this.$tip.css('left'), top: this.$tip.css('top')};
|
||||
}
|
||||
|
||||
// reset position to avoid text wrapping, etc.
|
||||
this.$tip.css({left: 0, top: 0}).appendTo(document.body);
|
||||
|
||||
// save default opacity
|
||||
if (this.opacity === undefined)
|
||||
this.opacity = this.$tip.css('opacity');
|
||||
|
||||
// check for images - this code is here (i.e. executed each time we show the tip and not on init) due to some browser inconsistencies
|
||||
var bgImage = this.$tip.css('background-image').match(reBgImage),
|
||||
arrow = this.$arrow.css('background-image').match(reBgImage);
|
||||
|
||||
if (bgImage) {
|
||||
var bgImagePNG = rePNG.test(bgImage[1]);
|
||||
// fallback to background-color/padding/border in IE6 if a PNG is used
|
||||
if (ie6 && bgImagePNG) {
|
||||
this.$tip.css('background-image', 'none');
|
||||
this.$inner.css({margin: 0, border: 0, padding: 0});
|
||||
bgImage = bgImagePNG = false;
|
||||
} else {
|
||||
this.$tip.prepend('<table class="fallback" border="0" cellpadding="0" cellspacing="0"><tr><td class="tip-top tip-bg-image" colspan="2"><span></span></td><td class="tip-right tip-bg-image" rowspan="2"><span></span></td></tr><tr><td class="tip-left tip-bg-image" rowspan="2"><span></span></td><td></td></tr><tr><td class="tip-bottom tip-bg-image" colspan="2"><span></span></td></tr></table>')
|
||||
.css({border: 0, padding: 0, 'background-image': 'none', 'background-color': 'transparent'})
|
||||
.find('.tip-bg-image').css('background-image', 'url("' + bgImage[1] +'")').end()
|
||||
.find('td').eq(3).append(this.$inner);
|
||||
}
|
||||
// disable fade effect in IE due to Alpha filter + translucent PNG issue
|
||||
if (bgImagePNG && !$.support.opacity)
|
||||
this.opts.fade = false;
|
||||
}
|
||||
// IE arrow fixes
|
||||
if (arrow && !$.support.opacity) {
|
||||
// disable arrow in IE6 if using a PNG
|
||||
if (ie6 && rePNG.test(arrow[1])) {
|
||||
arrow = false;
|
||||
this.$arrow.css('background-image', 'none');
|
||||
}
|
||||
// disable fade effect in IE due to Alpha filter + translucent PNG issue
|
||||
this.opts.fade = false;
|
||||
}
|
||||
|
||||
var $table = this.$tip.find('table.fallback');
|
||||
if (ie6) {
|
||||
// fix min/max-width in IE6
|
||||
this.$tip[0].style.width = '';
|
||||
$table.width('auto').find('td').eq(3).width('auto');
|
||||
var tipW = this.$tip.width(),
|
||||
minW = parseInt(this.$tip.css('min-width')),
|
||||
maxW = parseInt(this.$tip.css('max-width'));
|
||||
if (!isNaN(minW) && tipW < minW)
|
||||
tipW = minW;
|
||||
else if (!isNaN(maxW) && tipW > maxW)
|
||||
tipW = maxW;
|
||||
this.$tip.add($table).width(tipW).eq(0).find('td').eq(3).width('100%');
|
||||
} else if ($table[0]) {
|
||||
// fix the table width if we are using a background image
|
||||
// IE9, FF4 use float numbers for width/height so use getComputedStyle for them to avoid text wrapping
|
||||
// for details look at: http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
|
||||
$table.width('auto').find('td').eq(3).width('auto').end().end().width(document.defaultView && document.defaultView.getComputedStyle && parseFloat(document.defaultView.getComputedStyle(this.$tip[0], null).width) || this.$tip.width()).find('td').eq(3).width('100%');
|
||||
}
|
||||
this.tipOuterW = this.$tip.outerWidth();
|
||||
this.tipOuterH = this.$tip.outerHeight();
|
||||
|
||||
this.calcPos();
|
||||
|
||||
// position and show the arrow image
|
||||
if (arrow && this.pos.arrow) {
|
||||
this.$arrow[0].className = 'tip-arrow tip-arrow-' + this.pos.arrow;
|
||||
this.$arrow.css('visibility', 'inherit');
|
||||
}
|
||||
|
||||
if (async) {
|
||||
this.asyncAnimating = true;
|
||||
var self = this;
|
||||
this.$tip.css(currPos).animate({left: this.pos.l, top: this.pos.t}, 200, function() { self.asyncAnimating = false; });
|
||||
} else {
|
||||
this.$tip.css({left: this.pos.l, top: this.pos.t});
|
||||
}
|
||||
},
|
||||
display: function(hide) {
|
||||
var active = this.$tip.data('active');
|
||||
if (active && !hide || !active && hide)
|
||||
return;
|
||||
|
||||
this.$tip.stop();
|
||||
if ((this.opts.slide && this.pos.arrow || this.opts.fade) && (hide && this.opts.hideAniDuration || !hide && this.opts.showAniDuration)) {
|
||||
var from = {}, to = {};
|
||||
// this.pos.arrow is only undefined when alignX == alignY == 'center' and we don't need to slide in that rare case
|
||||
if (this.opts.slide && this.pos.arrow) {
|
||||
var prop, arr;
|
||||
if (this.pos.arrow == 'bottom' || this.pos.arrow == 'top') {
|
||||
prop = 'top';
|
||||
arr = 'bottom';
|
||||
} else {
|
||||
prop = 'left';
|
||||
arr = 'right';
|
||||
}
|
||||
var val = parseInt(this.$tip.css(prop));
|
||||
from[prop] = val + (hide ? 0 : (this.pos.arrow == arr ? -this.opts.slideOffset : this.opts.slideOffset));
|
||||
to[prop] = val + (hide ? (this.pos.arrow == arr ? this.opts.slideOffset : -this.opts.slideOffset) : 0) + 'px';
|
||||
}
|
||||
if (this.opts.fade) {
|
||||
from.opacity = hide ? this.$tip.css('opacity') : 0;
|
||||
to.opacity = hide ? 0 : this.opacity;
|
||||
}
|
||||
this.$tip.css(from).animate(to, this.opts[hide ? 'hideAniDuration' : 'showAniDuration']);
|
||||
}
|
||||
hide ? this.$tip.queue($.proxy(this.reset, this)) : this.$tip.css('visibility', 'inherit');
|
||||
this.$tip.data('active', !active);
|
||||
},
|
||||
disable: function() {
|
||||
this.reset();
|
||||
this.disabled = true;
|
||||
},
|
||||
enable: function() {
|
||||
this.disabled = false;
|
||||
},
|
||||
destroy: function() {
|
||||
this.reset();
|
||||
this.$tip.remove();
|
||||
delete this.$tip;
|
||||
this.content = null;
|
||||
this.$elm.unbind('.poshytip').removeData('title.poshytip').removeData('poshytip');
|
||||
tips.splice($.inArray(this, tips), 1);
|
||||
},
|
||||
clearTimeouts: function() {
|
||||
if (this.showTimeout) {
|
||||
clearTimeout(this.showTimeout);
|
||||
this.showTimeout = 0;
|
||||
}
|
||||
if (this.hideTimeout) {
|
||||
clearTimeout(this.hideTimeout);
|
||||
this.hideTimeout = 0;
|
||||
}
|
||||
},
|
||||
calcPos: function() {
|
||||
var pos = {l: 0, t: 0, arrow: ''},
|
||||
$win = $(window),
|
||||
win = {
|
||||
l: $win.scrollLeft(),
|
||||
t: $win.scrollTop(),
|
||||
w: $win.width(),
|
||||
h: $win.height()
|
||||
}, xL, xC, xR, yT, yC, yB;
|
||||
if (this.opts.alignTo == 'cursor') {
|
||||
xL = xC = xR = this.eventX;
|
||||
yT = yC = yB = this.eventY;
|
||||
} else { // this.opts.alignTo == 'target'
|
||||
var elmOffset = this.$elm.offset(),
|
||||
elm = {
|
||||
l: elmOffset.left,
|
||||
t: elmOffset.top,
|
||||
w: this.$elm.outerWidth(),
|
||||
h: this.$elm.outerHeight()
|
||||
};
|
||||
xL = elm.l + (this.opts.alignX != 'inner-right' ? 0 : elm.w); // left edge
|
||||
xC = xL + Math.floor(elm.w / 2); // h center
|
||||
xR = xL + (this.opts.alignX != 'inner-left' ? elm.w : 0); // right edge
|
||||
yT = elm.t + (this.opts.alignY != 'inner-bottom' ? 0 : elm.h); // top edge
|
||||
yC = yT + Math.floor(elm.h / 2); // v center
|
||||
yB = yT + (this.opts.alignY != 'inner-top' ? elm.h : 0); // bottom edge
|
||||
}
|
||||
|
||||
// keep in viewport and calc arrow position
|
||||
switch (this.opts.alignX) {
|
||||
case 'right':
|
||||
case 'inner-left':
|
||||
pos.l = xR + this.opts.offsetX;
|
||||
if (pos.l + this.tipOuterW > win.l + win.w)
|
||||
pos.l = win.l + win.w - this.tipOuterW;
|
||||
if (this.opts.alignX == 'right' || this.opts.alignY == 'center')
|
||||
pos.arrow = 'left';
|
||||
break;
|
||||
case 'center':
|
||||
pos.l = xC - Math.floor(this.tipOuterW / 2);
|
||||
if (pos.l + this.tipOuterW > win.l + win.w)
|
||||
pos.l = win.l + win.w - this.tipOuterW;
|
||||
else if (pos.l < win.l)
|
||||
pos.l = win.l;
|
||||
break;
|
||||
default: // 'left' || 'inner-right'
|
||||
pos.l = xL - this.tipOuterW - this.opts.offsetX;
|
||||
if (pos.l < win.l)
|
||||
pos.l = win.l;
|
||||
if (this.opts.alignX == 'left' || this.opts.alignY == 'center')
|
||||
pos.arrow = 'right';
|
||||
}
|
||||
switch (this.opts.alignY) {
|
||||
case 'bottom':
|
||||
case 'inner-top':
|
||||
pos.t = yB + this.opts.offsetY;
|
||||
// 'left' and 'right' need priority for 'target'
|
||||
if (!pos.arrow || this.opts.alignTo == 'cursor')
|
||||
pos.arrow = 'top';
|
||||
if (pos.t + this.tipOuterH > win.t + win.h) {
|
||||
pos.t = yT - this.tipOuterH - this.opts.offsetY;
|
||||
if (pos.arrow == 'top')
|
||||
pos.arrow = 'bottom';
|
||||
}
|
||||
break;
|
||||
case 'center':
|
||||
pos.t = yC - Math.floor(this.tipOuterH / 2);
|
||||
if (pos.t + this.tipOuterH > win.t + win.h)
|
||||
pos.t = win.t + win.h - this.tipOuterH;
|
||||
else if (pos.t < win.t)
|
||||
pos.t = win.t;
|
||||
break;
|
||||
default: // 'top' || 'inner-bottom'
|
||||
pos.t = yT - this.tipOuterH - this.opts.offsetY;
|
||||
// 'left' and 'right' need priority for 'target'
|
||||
if (!pos.arrow || this.opts.alignTo == 'cursor')
|
||||
pos.arrow = 'bottom';
|
||||
if (pos.t < win.t) {
|
||||
pos.t = yB + this.opts.offsetY;
|
||||
if (pos.arrow == 'bottom')
|
||||
pos.arrow = 'top';
|
||||
}
|
||||
}
|
||||
this.pos = pos;
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.poshytip = function(options) {
|
||||
if (typeof options == 'string') {
|
||||
var args = arguments,
|
||||
method = options;
|
||||
Array.prototype.shift.call(args);
|
||||
// unhook live events if 'destroy' is called
|
||||
if (method == 'destroy')
|
||||
this.die('mouseenter.poshytip').die('focus.poshytip');
|
||||
return this.each(function() {
|
||||
var poshytip = $(this).data('poshytip');
|
||||
if (poshytip && poshytip[method])
|
||||
poshytip[method].apply(poshytip, args);
|
||||
});
|
||||
}
|
||||
|
||||
var opts = $.extend({}, $.fn.poshytip.defaults, options);
|
||||
|
||||
// generate CSS for this tip class if not already generated
|
||||
if (!$('#poshytip-css-' + opts.className)[0])
|
||||
$(['<style id="poshytip-css-',opts.className,'" type="text/css">',
|
||||
'div.',opts.className,'{visibility:hidden;position:absolute;top:0;left:0;}',
|
||||
'div.',opts.className,' table, div.',opts.className,' td{margin:0;font-family:inherit;font-size:inherit;font-weight:inherit;font-style:inherit;font-variant:inherit;}',
|
||||
'div.',opts.className,' td.tip-bg-image span{display:block;font:1px/1px sans-serif;height:',opts.bgImageFrameSize,'px;width:',opts.bgImageFrameSize,'px;overflow:hidden;}',
|
||||
'div.',opts.className,' td.tip-right{background-position:100% 0;}',
|
||||
'div.',opts.className,' td.tip-bottom{background-position:100% 100%;}',
|
||||
'div.',opts.className,' td.tip-left{background-position:0 100%;}',
|
||||
'div.',opts.className,' div.tip-inner{background-position:-',opts.bgImageFrameSize,'px -',opts.bgImageFrameSize,'px;}',
|
||||
'div.',opts.className,' div.tip-arrow{visibility:hidden;position:absolute;overflow:hidden;font:1px/1px sans-serif;}',
|
||||
'</style>'].join('')).appendTo('head');
|
||||
|
||||
// check if we need to hook live events
|
||||
if (opts.liveEvents && opts.showOn != 'none') {
|
||||
var deadOpts = $.extend({}, opts, { liveEvents: false });
|
||||
switch (opts.showOn) {
|
||||
case 'hover':
|
||||
this.live('mouseenter.poshytip', function() {
|
||||
var $this = $(this);
|
||||
if (!$this.data('poshytip'))
|
||||
$this.poshytip(deadOpts).poshytip('mouseenter');
|
||||
});
|
||||
break;
|
||||
case 'focus':
|
||||
this.live('focus.poshytip', function() {
|
||||
var $this = $(this);
|
||||
if (!$this.data('poshytip'))
|
||||
$this.poshytip(deadOpts).poshytip('show');
|
||||
});
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.each(function() {
|
||||
new $.Poshytip(this, opts);
|
||||
});
|
||||
}
|
||||
|
||||
// default settings
|
||||
$.fn.poshytip.defaults = {
|
||||
content: '[title]', // content to display ('[title]', 'string', element, function(updateCallback){...}, jQuery)
|
||||
className: 'tip-yellow', // class for the tips
|
||||
bgImageFrameSize: 10, // size in pixels for the background-image (if set in CSS) frame around the inner content of the tip
|
||||
showTimeout: 500, // timeout before showing the tip (in milliseconds 1000 == 1 second)
|
||||
hideTimeout: 100, // timeout before hiding the tip
|
||||
timeOnScreen: 0, // timeout before automatically hiding the tip after showing it (set to > 0 in order to activate)
|
||||
showOn: 'hover', // handler for showing the tip ('hover', 'focus', 'none') - use 'none' to trigger it manually
|
||||
liveEvents: false, // use live events
|
||||
alignTo: 'cursor', // align/position the tip relative to ('cursor', 'target')
|
||||
alignX: 'right', // horizontal alignment for the tip relative to the mouse cursor or the target element
|
||||
// ('right', 'center', 'left', 'inner-left', 'inner-right') - 'inner-*' matter if alignTo:'target'
|
||||
alignY: 'top', // vertical alignment for the tip relative to the mouse cursor or the target element
|
||||
// ('bottom', 'center', 'top', 'inner-bottom', 'inner-top') - 'inner-*' matter if alignTo:'target'
|
||||
offsetX: -22, // offset X pixels from the default position - doesn't matter if alignX:'center'
|
||||
offsetY: 18, // offset Y pixels from the default position - doesn't matter if alignY:'center'
|
||||
allowTipHover: true, // allow hovering the tip without hiding it onmouseout of the target - matters only if showOn:'hover'
|
||||
followCursor: false, // if the tip should follow the cursor - matters only if showOn:'hover' and alignTo:'cursor'
|
||||
fade: true, // use fade animation
|
||||
slide: true, // use slide animation
|
||||
slideOffset: 8, // slide animation offset
|
||||
showAniDuration: 300, // show animation duration - set to 0 if you don't want show animation
|
||||
hideAniDuration: 300 // hide animation duration - set to 0 if you don't want hide animation
|
||||
};
|
||||
|
||||
})(jQuery);
|
10
makezip
@ -1,10 +0,0 @@
|
||||
cd dist
|
||||
|
||||
#extract version
|
||||
version=$(head -1 bootstrap-editable/js/bootstrap-editable.js | sed -n 's/^.*v\([0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p')
|
||||
|
||||
mkdir -p zip
|
||||
rm -rf zip/*.zip
|
||||
zip -rT zip/bootstrap-editable-$version.zip bootstrap-editable LICENSE-GPL LICENSE-MIT README.md CHANGELOG.txt
|
||||
zip -rT zip/jqueryui-editable-$version.zip jqueryui-editable LICENSE-GPL LICENSE-MIT README.md CHANGELOG.txt
|
||||
zip -rT zip/jquery-editable-$version.zip jquery-editable LICENSE-GPL LICENSE-MIT README.md CHANGELOG.txt
|
11
package.json
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "x-editable",
|
||||
"name": "X-editable",
|
||||
"title": "X-editable",
|
||||
"description": "In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery",
|
||||
"version": "1.0.0",
|
||||
"homepage": "https://github.com/vitalets/x-editable",
|
||||
"homepage": "http://github.com/vitalets/x-editable",
|
||||
"author": {
|
||||
"name": "Vitaliy Potapov",
|
||||
"email": "noginsk@rambler.ru"
|
||||
@ -19,10 +19,6 @@
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/vitalets/x-editable/blob/master/LICENSE-MIT"
|
||||
},
|
||||
{
|
||||
"type": "GPL",
|
||||
"url": "https://github.com/vitalets/x-editable/blob/master/LICENSE-GPL"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
@ -30,8 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.3.11",
|
||||
"grunt-contrib": "0.1.1",
|
||||
"moment": "1.7.0"
|
||||
"grunt-contrib": "0.1.1"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
@ -1,48 +1,56 @@
|
||||
/**
|
||||
* Editable Container
|
||||
* Container can be popover, inline form or whatever
|
||||
* Container must provide following:
|
||||
* 1. methods:
|
||||
* show(),
|
||||
* hide(),
|
||||
* tip() - returns jquery object of container element
|
||||
* option()
|
||||
*
|
||||
* 2. events:
|
||||
* - save
|
||||
* - cancel
|
||||
*
|
||||
* 3. settings: trigger, value, placement
|
||||
*/
|
||||
Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br>
|
||||
This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br>
|
||||
Final realization can be different: bootstrap-popover, jqueryui-tooltip, poshytip, inline-div. It depends on which js file you include.<br>
|
||||
Applied as jQuery method.
|
||||
|
||||
@class editableContainer
|
||||
@uses editableform
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
//Constructor
|
||||
|
||||
var EditableContainer = function (element, options) {
|
||||
this.init(element, options);
|
||||
};
|
||||
|
||||
|
||||
//methods
|
||||
EditableContainer.prototype = {
|
||||
containerName: null, //tbd in child class
|
||||
innerCss: null, //tbd in child class
|
||||
init: function(element, options) {
|
||||
this.$element = $(element);
|
||||
//todo: what is in priority: data or js?
|
||||
this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableform.utils.getConfigData(this.$element), options);
|
||||
this.splitOptions();
|
||||
this.initContainer();
|
||||
|
||||
|
||||
//bind 'destroyed' listener to destroy container when element is removed from dom
|
||||
this.$element.on('destroyed', $.proxy(function(){
|
||||
this.destroy();
|
||||
}, this));
|
||||
},
|
||||
|
||||
initContainer: function(){
|
||||
this.call(this.options);
|
||||
|
||||
//split options on containerOptions and formOptions
|
||||
splitOptions: function() {
|
||||
this.containerOptions = {};
|
||||
this.formOptions = {};
|
||||
var cDef = $.fn[this.containerName].defaults;
|
||||
for(var k in this.options) {
|
||||
if(k in cDef) {
|
||||
this.containerOptions[k] = this.options[k];
|
||||
} else {
|
||||
this.formOptions[k] = this.options[k];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initContainer: function(){
|
||||
this.call(this.containerOptions);
|
||||
},
|
||||
|
||||
initForm: function() {
|
||||
this.$form = $('<div>')
|
||||
.editableform(this.options)
|
||||
.editableform(this.formOptions)
|
||||
.on({
|
||||
save: $.proxy(this.save, this),
|
||||
cancel: $.proxy(this.cancel, this),
|
||||
@ -52,92 +60,188 @@
|
||||
return this.$form;
|
||||
},
|
||||
|
||||
/*
|
||||
Returns jquery object of container
|
||||
@method tip()
|
||||
*/
|
||||
tip: function() {
|
||||
return this.container().$tip;
|
||||
return this.container().$tip;
|
||||
},
|
||||
|
||||
//return instance of container
|
||||
|
||||
container: function() {
|
||||
return this.$element.data(this.containerName);
|
||||
return this.$element.data(this.containerName);
|
||||
},
|
||||
|
||||
//call container's method
|
||||
|
||||
call: function() {
|
||||
this.$element[this.containerName].apply(this.$element, arguments);
|
||||
this.$element[this.containerName].apply(this.$element, arguments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
Shows container with form
|
||||
@method show()
|
||||
**/
|
||||
show: function () {
|
||||
this.call('show');
|
||||
this.tip().addClass('editable-container');
|
||||
|
||||
|
||||
this.initForm();
|
||||
this.tip().find(this.innerCss).empty().append(this.$form);
|
||||
this.$form.editableform('render');
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.call('hide');
|
||||
},
|
||||
|
||||
setPosition: function() {
|
||||
//tbd in child class
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
if(this.options.autohide) {
|
||||
this.hide();
|
||||
}
|
||||
this.$element.triggerHandler('cancel');
|
||||
},
|
||||
|
||||
save: function(e, params) {
|
||||
if(this.options.autohide) {
|
||||
this.hide();
|
||||
}
|
||||
this.$element.triggerHandler('save', params);
|
||||
},
|
||||
|
||||
option: function(key, value) {
|
||||
this.options[key] = value;
|
||||
this.call('option', key, value);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.call('destroy');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Hides container with form
|
||||
@method hide()
|
||||
**/
|
||||
hide: function() {
|
||||
this.call('hide');
|
||||
},
|
||||
|
||||
/*
|
||||
Updates the position of container when content changed.
|
||||
@method setPosition()
|
||||
*/
|
||||
setPosition: function() {
|
||||
//tbd in child class
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
if(this.options.autohide) {
|
||||
this.hide();
|
||||
}
|
||||
/**
|
||||
Fired when form was cancelled by user
|
||||
|
||||
@event cancel
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$element.triggerHandler('cancel');
|
||||
},
|
||||
|
||||
save: function(e, params) {
|
||||
if(this.options.autohide) {
|
||||
this.hide();
|
||||
}
|
||||
/**
|
||||
Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance
|
||||
|
||||
@event save
|
||||
@param {Object} event event object
|
||||
@param {Object} params additional params
|
||||
@param {mixed} params.newValue submitted value
|
||||
@param {Object} params.response ajax response
|
||||
@example
|
||||
$('#username').on('save', function(e, params) {
|
||||
//assuming server response: '{success: true}'
|
||||
var pk = $(this).data('editableContainer').options.pk;
|
||||
if(params.response && params.response.success) {
|
||||
alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!');
|
||||
} else {
|
||||
alert('error!');
|
||||
}
|
||||
});
|
||||
**/
|
||||
this.$element.triggerHandler('save', params);
|
||||
},
|
||||
|
||||
/**
|
||||
Sets new option
|
||||
|
||||
@method option(key, value)
|
||||
@param {string} key
|
||||
@param {mixed} value
|
||||
**/
|
||||
option: function(key, value) {
|
||||
this.options[key] = value;
|
||||
if(key in this.containerOptions) {
|
||||
this.containerOptions[key] = value;
|
||||
this.setContainerOption(key, value);
|
||||
} else {
|
||||
this.formOptions[key] = value;
|
||||
if(this.$form) {
|
||||
this.$form.editableform('option', key, value);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setContainerOption: function(key, value) {
|
||||
this.call('option', key, value);
|
||||
},
|
||||
|
||||
/**
|
||||
Destroys the container instance
|
||||
@method destroy()
|
||||
**/
|
||||
destroy: function() {
|
||||
this.call('destroy');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
jQuery method to initialize editableContainer.
|
||||
|
||||
//jQuery plugin definition
|
||||
@method $().editableContainer(options)
|
||||
@params {Object} options
|
||||
@example
|
||||
$('#edit').editableContainer({
|
||||
type: 'text',
|
||||
url: 'post.php',
|
||||
pk: 1,
|
||||
value: 'hello'
|
||||
});
|
||||
**/
|
||||
$.fn.editableContainer = function (option) {
|
||||
var args = arguments;
|
||||
return this.each(function () {
|
||||
var $this = $(this),
|
||||
dataKey = 'editableContainer',
|
||||
data = $this.data(dataKey),
|
||||
options = typeof option === 'object' && option;
|
||||
dataKey = 'editableContainer',
|
||||
data = $this.data(dataKey),
|
||||
options = typeof option === 'object' && option;
|
||||
|
||||
if (!data) {
|
||||
$this.data(dataKey, (data = new EditableContainer(this, options)));
|
||||
}
|
||||
|
||||
|
||||
if (typeof option === 'string') { //call method
|
||||
data[option].apply(data, Array.prototype.slice.call(args, 1));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//store constructor
|
||||
$.fn.editableContainer.Constructor = EditableContainer;
|
||||
|
||||
|
||||
//defaults - must be redefined!
|
||||
$.fn.editableContainer.defaults = {
|
||||
trigger: 'manual',
|
||||
value: null,
|
||||
placement: 'top',
|
||||
autohide: true
|
||||
/**
|
||||
Initial value of form input
|
||||
|
||||
@property value
|
||||
@type mixed
|
||||
@default null
|
||||
@private
|
||||
**/
|
||||
value: null,
|
||||
/**
|
||||
Placement of container relative to element. Can be <code>top|right|bottom|left</code>. Not used for inline container.
|
||||
|
||||
@property placement
|
||||
@type string
|
||||
@default 'top'
|
||||
**/
|
||||
placement: 'top',
|
||||
/**
|
||||
Wether to hide container on save/cancel.
|
||||
|
||||
@property autohide
|
||||
@type boolean
|
||||
@default true
|
||||
@private
|
||||
**/
|
||||
autohide: true
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* workaround to have 'destroyed' event to destroy popover when element is destroyed
|
||||
* see http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
|
||||
@ -149,5 +253,5 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}(window.jQuery));
|
@ -17,6 +17,11 @@
|
||||
}
|
||||
},
|
||||
|
||||
splitOptions: function() {
|
||||
this.containerOptions = {};
|
||||
this.formOptions = this.options;
|
||||
},
|
||||
|
||||
tip: function() {
|
||||
return this.$form;
|
||||
},
|
||||
|
@ -6,12 +6,25 @@
|
||||
(function ($) {
|
||||
|
||||
//extend methods
|
||||
/**
|
||||
Container based on Bootstrap Popover
|
||||
|
||||
@class editableContainer (popover)
|
||||
**/
|
||||
$.extend($.fn.editableContainer.Constructor.prototype, {
|
||||
containerName: 'popover',
|
||||
innerCss: '.popover-content p',
|
||||
|
||||
option: function(key, value) {
|
||||
this.options[key] = value;
|
||||
initContainer: function(){
|
||||
$.extend(this.containerOptions, {
|
||||
trigger: 'manual',
|
||||
selector: 'false',
|
||||
content: ' '
|
||||
});
|
||||
this.call(this.containerOptions);
|
||||
},
|
||||
|
||||
setContainerOption: function(key, value) {
|
||||
this.container().options[key] = value;
|
||||
},
|
||||
|
||||
@ -36,13 +49,9 @@
|
||||
tp = {top:pos.top + pos.height, left:pos.left + pos.width / 2 - actualWidth / 2};
|
||||
break;
|
||||
case 'top':
|
||||
/* For Bootstrap 2.1.0 - 2.1.1: 10 pixels needed to correct popover position. See https://github.com/twitter/bootstrap/issues/4665 */
|
||||
//if($tip.find('.arrow').get(0).offsetHeight === 10) {actualHeight += 10;}
|
||||
tp = {top:pos.top - actualHeight, left:pos.left + pos.width / 2 - actualWidth / 2};
|
||||
break;
|
||||
case 'left':
|
||||
/* For Bootstrap 2.1.0 - 2.1.1: 10 pixels needed to correct popover position. See https://github.com/twitter/bootstrap/issues/4665 */
|
||||
//if($tip.find('.arrow').get(0).offsetWidth === 10) {actualWidth += 10;}
|
||||
tp = {top:pos.top + pos.height / 2 - actualHeight / 2, left:pos.left - actualWidth};
|
||||
break;
|
||||
case 'right':
|
||||
@ -55,8 +64,10 @@
|
||||
});
|
||||
|
||||
//defaults
|
||||
/*
|
||||
$.fn.editableContainer.defaults = $.extend({}, $.fn.popover.defaults, $.fn.editableContainer.defaults, {
|
||||
content: ' '
|
||||
});
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
}(window.jQuery));
|
@ -12,10 +12,17 @@
|
||||
|
||||
initContainer: function(){
|
||||
this.handlePlacement();
|
||||
this.call(this.options);
|
||||
|
||||
$.extend(this.containerOptions, {
|
||||
showOn: 'none',
|
||||
content: '',
|
||||
alignTo: 'target'
|
||||
});
|
||||
|
||||
this.call(this.containerOptions);
|
||||
|
||||
var $content = $('<div>')
|
||||
.append($('<label>').text(this.options.title || this.$element.data( "ui-tooltip-title") || this.$element.data( "originalTitle")))
|
||||
.append($('<label>').text(this.options.title || this.$element.data( "title") || this.$element.data( "originalTitle")))
|
||||
.append(this.initForm());
|
||||
|
||||
this.call('update', $content);
|
||||
@ -25,7 +32,6 @@
|
||||
this.$form.editableform('render');
|
||||
this.tip().addClass('editable-container');
|
||||
|
||||
|
||||
this.call('show');
|
||||
this.$form.data('editableform').input.activate();
|
||||
},
|
||||
@ -59,20 +65,18 @@
|
||||
break;
|
||||
}
|
||||
|
||||
this.options.alignX = x;
|
||||
this.options.offsetX = ox;
|
||||
|
||||
this.options.alignY = y;
|
||||
this.options.offsetY = oy;
|
||||
$.extend(this.containerOptions, {
|
||||
alignX: x,
|
||||
offsetX: ox,
|
||||
alignY: y,
|
||||
offsetY:oy
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//defaults
|
||||
$.fn.editableContainer.defaults = $.extend({}, $.fn.poshytip.defaults, $.fn.editableContainer.defaults, {
|
||||
className: 'tip-yellowsimple',
|
||||
showOn: 'none',
|
||||
content: '',
|
||||
alignTo: 'target'
|
||||
$.fn.editableContainer.defaults = $.extend({}, $.fn.editableContainer.defaults, {
|
||||
className: 'tip-yellowsimple'
|
||||
});
|
||||
|
||||
|
||||
|
@ -6,21 +6,48 @@
|
||||
(function ($) {
|
||||
|
||||
//extend methods
|
||||
/**
|
||||
Container based on jQuery UI Tooltip
|
||||
|
||||
@class editableContainer (tooltip)
|
||||
**/
|
||||
$.extend($.fn.editableContainer.Constructor.prototype, {
|
||||
containerName: 'tooltip',
|
||||
innerCss: '.ui-tooltip-content',
|
||||
|
||||
//split options on containerOptions and formOptions
|
||||
splitOptions: function() {
|
||||
this.containerOptions = {};
|
||||
this.formOptions = {};
|
||||
//defaults for tooltip
|
||||
var cDef = $.ui[this.containerName].prototype.options;
|
||||
for(var k in this.options) {
|
||||
if(k in cDef) {
|
||||
this.containerOptions[k] = this.options[k];
|
||||
} else {
|
||||
this.formOptions[k] = this.options[k];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initContainer: function(){
|
||||
this.handlePlacement();
|
||||
this.options.open = $.proxy(function() {
|
||||
//disable events hiding tooltip by default
|
||||
this.container()._on(this.container().element, {
|
||||
mouseleave: function(e){ e.stopImmediatePropagation(); },
|
||||
focusout: function(e){ e.stopImmediatePropagation(); }
|
||||
});
|
||||
}, this);
|
||||
this.call(this.options);
|
||||
//disable standart event to show tooltip
|
||||
$.extend(this.containerOptions, {
|
||||
items: '*',
|
||||
content: ' ',
|
||||
track: false,
|
||||
open: $.proxy(function() {
|
||||
//disable events hiding tooltip by default
|
||||
this.container()._on(this.container().element, {
|
||||
mouseleave: function(e){ e.stopImmediatePropagation(); },
|
||||
focusout: function(e){ e.stopImmediatePropagation(); }
|
||||
});
|
||||
}, this)
|
||||
});
|
||||
|
||||
this.call(this.containerOptions);
|
||||
|
||||
//disable standart triggering tooltip event
|
||||
this.container()._off(this.container().element, 'mouseover focusin');
|
||||
},
|
||||
|
||||
@ -47,7 +74,7 @@
|
||||
setPosition: function() {
|
||||
this.tip().position( $.extend({
|
||||
of: this.$element
|
||||
}, this.options.position ) );
|
||||
}, this.containerOptions.position ) );
|
||||
},
|
||||
|
||||
handlePlacement: function() {
|
||||
@ -79,19 +106,20 @@
|
||||
break;
|
||||
}
|
||||
|
||||
this.options.position = $.extend({}, this.options.position, pos);
|
||||
this.containerOptions.position = pos;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
//jqueryui tooltip destroy itself
|
||||
}
|
||||
destroy: function() {
|
||||
//jqueryui tooltip destroys itself
|
||||
}
|
||||
});
|
||||
|
||||
//defaults
|
||||
/*
|
||||
$.fn.editableContainer.defaults = $.extend({}, $.fn.tooltip.defaults, $.fn.editableContainer.defaults, {
|
||||
items: '*',
|
||||
content: ' ',
|
||||
position: {}
|
||||
});
|
||||
*/
|
||||
|
||||
}(window.jQuery));
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Editable-form Bootstrap engine
|
||||
/*
|
||||
Editableform based on Twitter Bootstrap
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Editable-form jQuery UI engine
|
||||
/*
|
||||
Editableform based on jQuery UI
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* EditableForm utils
|
||||
* EditableForm utilites
|
||||
*/
|
||||
(function ($) {
|
||||
$.extend($.fn.editableform, {
|
||||
|
@ -30,14 +30,12 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* for inline datepicker do not to inherit from table (bootstrap) */
|
||||
.table-striped .editableform table td, .editableform table th {
|
||||
border: none !important;
|
||||
.editableform textarea {
|
||||
height: 150px; /*default height for textarea*/
|
||||
}
|
||||
|
||||
.table-striped .editableform table tr:nth-child(2n+1) td,
|
||||
.table-striped .editableform table tr:nth-child(2n+1) th {
|
||||
background-color: transparent;
|
||||
}
|
||||
.editableform .editable-date {
|
||||
float: left;
|
||||
padding: 0;
|
||||
margin: 0 0 9px 0;
|
||||
}
|
@ -1,21 +1,14 @@
|
||||
/**
|
||||
* Editable-form plugin
|
||||
* Form with single input element, two buttons and automatic loader, shown on init/submit
|
||||
* Plugin applied to DIV tag and show form inside
|
||||
* Input must be one of following types:
|
||||
* - text
|
||||
* - textarea
|
||||
* - select
|
||||
* - date
|
||||
* - <your input here>
|
||||
*
|
||||
* EVENTS:
|
||||
* - render
|
||||
* - resize
|
||||
* - save
|
||||
*/
|
||||
(function ($) {
|
||||
Form with single input element, two buttons and two states: normal/loading.
|
||||
Applied as jQuery method to DIV tag (not to form tag!)
|
||||
Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
|
||||
@class editableform
|
||||
@uses text
|
||||
@uses textarea
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var EditableForm = function (element, options) {
|
||||
this.options = $.extend({}, $.fn.editableform.defaults, options);
|
||||
this.$container = $(element); //div, containing form
|
||||
@ -42,13 +35,23 @@
|
||||
initTemplate: function() {
|
||||
this.$form = $($.fn.editableform.template);
|
||||
},
|
||||
/**
|
||||
Renders editableform
|
||||
|
||||
@method render
|
||||
**/
|
||||
render: function() {
|
||||
this.$loading = $(this.options.loading);
|
||||
this.$loading = $($.fn.editableform.loading);
|
||||
this.$container.empty().append(this.$loading);
|
||||
this.showLoading();
|
||||
|
||||
this.initTemplate();
|
||||
|
||||
/**
|
||||
Fired when rendering starts
|
||||
@event rendering
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$container.triggerHandler('rendering');
|
||||
|
||||
//render input
|
||||
@ -72,6 +75,11 @@
|
||||
}, this));
|
||||
},
|
||||
cancel: function() {
|
||||
/**
|
||||
Fired when form was cancelled by user
|
||||
@event cancel
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$container.triggerHandler('cancel');
|
||||
},
|
||||
showLoading: function() {
|
||||
@ -96,7 +104,12 @@
|
||||
showForm: function() {
|
||||
this.$loading.hide();
|
||||
this.$form.show();
|
||||
this.input.activate();
|
||||
this.input.activate();
|
||||
/**
|
||||
Fired when form is shown
|
||||
@event show
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$container.triggerHandler('show');
|
||||
},
|
||||
|
||||
@ -145,10 +158,23 @@
|
||||
.done($.proxy(function(response) {
|
||||
this.error(false);
|
||||
this.value = newValue;
|
||||
/**
|
||||
Fired when form is submitted
|
||||
@event save
|
||||
@param {Object} event event object
|
||||
@param {Object} params additional params
|
||||
@param {mixed} params.newValue submitted value
|
||||
@param {Object} params.response ajax response
|
||||
|
||||
@example
|
||||
$('#form-div').on('save'), function(e, params){
|
||||
if(params.newValue === 'username') {...}
|
||||
});
|
||||
**/
|
||||
this.$container.triggerHandler('save', {newValue: newValue, response: response});
|
||||
}, this))
|
||||
.fail($.proxy(function(xhr) {
|
||||
this.error(xhr.responseText || xhr.statusText || 'Unknown error!');
|
||||
this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
|
||||
this.showForm();
|
||||
}, this));
|
||||
},
|
||||
@ -170,13 +196,16 @@
|
||||
pk: pk
|
||||
});
|
||||
|
||||
//send ajax to server and return deferred object
|
||||
return $.ajax({
|
||||
url : (typeof this.options.url === 'function') ? this.options.url.call(this) : this.options.url,
|
||||
data : params,
|
||||
type : 'post',
|
||||
dataType: 'json'
|
||||
});
|
||||
if(typeof this.options.url === 'function') { //user's function
|
||||
return this.options.url.call(this, params);
|
||||
} else { //send ajax to server and return deferred object
|
||||
return $.ajax({
|
||||
url : this.options.url,
|
||||
data : params,
|
||||
type : 'post',
|
||||
dataType: 'json'
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -194,7 +223,22 @@
|
||||
}
|
||||
};
|
||||
|
||||
//jquery plugin definition
|
||||
/*
|
||||
Initialize editableform. Applied to jQuery object.
|
||||
|
||||
@method $().editableform(options)
|
||||
@params {Object} options
|
||||
@example
|
||||
var $form = $('<div>').editableform({
|
||||
type: 'text',
|
||||
name: 'username',
|
||||
url: 'post.php',
|
||||
value: 'vitaliy'
|
||||
});
|
||||
|
||||
//to display form you should call 'render' method
|
||||
$form.editableform('render');
|
||||
*/
|
||||
$.fn.editableform = function (option) {
|
||||
var args = arguments;
|
||||
return this.each(function () {
|
||||
@ -217,14 +261,88 @@
|
||||
//defaults
|
||||
$.fn.editableform.defaults = {
|
||||
/* see also defaults for input */
|
||||
|
||||
/**
|
||||
Type of input. Can be <code>text|textarea|select|date</code>
|
||||
|
||||
@property type
|
||||
@type string
|
||||
@default 'text'
|
||||
**/
|
||||
type: 'text',
|
||||
/**
|
||||
Url for submit, e.g. <code>post.php</code>
|
||||
If function - it will be called instead of ajax. Function can return deferred object to run fail/done callbacks.
|
||||
|
||||
@property url
|
||||
@type string|function
|
||||
@default null
|
||||
@example
|
||||
url: function(params) {
|
||||
if(params.value === 'abc') {
|
||||
var d = new $.Deferred;
|
||||
return d.reject('field cannot be "abc"'); //returning error via deferred object
|
||||
} else {
|
||||
someModel.set(params.name, params.value); //save data in some js model
|
||||
}
|
||||
}
|
||||
**/
|
||||
url:null,
|
||||
/**
|
||||
Additional params for submit
|
||||
|
||||
@property params
|
||||
@type object
|
||||
@default null
|
||||
**/
|
||||
params:null,
|
||||
/**
|
||||
Name of field. Will be submitted on server. Can be taken from <code>id</code> attribute
|
||||
|
||||
@property name
|
||||
@type string
|
||||
@default null
|
||||
**/
|
||||
name: null,
|
||||
/**
|
||||
Primary key of editable object (e.g. record id in database). Use Object for composite keys.
|
||||
|
||||
@property pk
|
||||
@type string|object|function
|
||||
@default null
|
||||
**/
|
||||
pk: null,
|
||||
value: null, //initial value
|
||||
send: 'auto', //always|auto|never
|
||||
loading: '<div class="editableform-loading"></div>',
|
||||
/**
|
||||
Initial value. If not defined - will be taken from element's content.
|
||||
For __select__ type should be defined (as it is ID of shown text).
|
||||
|
||||
@property value
|
||||
@type string|object
|
||||
@default null
|
||||
**/
|
||||
value: null,
|
||||
/**
|
||||
Strategy for sending data on server. Can be <code>auto|always|never</code>.
|
||||
When 'auto' data will be sent on server only if pk defined, otherwise new value will be stored in element.
|
||||
|
||||
@property send
|
||||
@type string
|
||||
@default 'auto'
|
||||
**/
|
||||
send: 'auto',
|
||||
/**
|
||||
Function for client-side validation. If returns string - means validation not passed and string showed as error.
|
||||
|
||||
@property validate
|
||||
@type function
|
||||
@default null
|
||||
@example
|
||||
validate: function(value) {
|
||||
if($.trim(value) == '') {
|
||||
return 'This field is required';
|
||||
}
|
||||
}
|
||||
**/
|
||||
validate: null
|
||||
};
|
||||
|
||||
@ -237,14 +355,18 @@
|
||||
'<div class="editable-error-block"></div>' +
|
||||
'</form>';
|
||||
|
||||
//loading div
|
||||
$.fn.editableform.loading = '<div class="editableform-loading"></div>';
|
||||
|
||||
//error class attahced to control-group
|
||||
$.fn.editableform.errorGroupClass = null;
|
||||
$.fn.editableform.errorGroupClass = null;
|
||||
|
||||
//error class attahced to editable-error-block
|
||||
$.fn.editableform.errorBlockClass = 'editable-error';
|
||||
|
||||
|
||||
//input types
|
||||
$.fn.editableform.types = {};
|
||||
$.fn.editableform.utils = {};
|
||||
//input types
|
||||
$.fn.editableform.types = {};
|
||||
//utils
|
||||
$.fn.editableform.utils = {};
|
||||
|
||||
}(window.jQuery));
|
@ -1,11 +1,9 @@
|
||||
/**
|
||||
* Editable-element
|
||||
* Initialize HTML element that can be editable by click.
|
||||
* 1. methods
|
||||
*
|
||||
* 2. events
|
||||
* - render
|
||||
*/
|
||||
Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
|
||||
@class editable
|
||||
@uses editableContainer
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var Editable = function (element, options) {
|
||||
@ -27,7 +25,7 @@
|
||||
|
||||
//editableContainer must be defined
|
||||
if(!$.fn.editableContainer) {
|
||||
$.error('You must define $.fn.editableContainer via including corresponding file (e.g. editablePopover)');
|
||||
$.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -89,11 +87,28 @@
|
||||
} else {
|
||||
this.enable();
|
||||
}
|
||||
/**
|
||||
Fired each time when element's text is rendered. Occurs on initialization and on each update of value.
|
||||
Can be used for display customization.
|
||||
|
||||
@event render
|
||||
@param {Object} event event object
|
||||
@param {Object} editable editable instance
|
||||
@example
|
||||
$('#action').on('render', function(e, editable) {
|
||||
var colors = {0: "gray", 1: "green", 2: "blue", 3: "red"};
|
||||
$(this).css("color", colors[editable.value]);
|
||||
});
|
||||
**/
|
||||
this.$element.triggerHandler('render', this);
|
||||
this.isInit = false;
|
||||
}, this));
|
||||
},
|
||||
|
||||
/**
|
||||
Enables editable
|
||||
@method enable()
|
||||
**/
|
||||
enable: function() {
|
||||
this.options.disabled = false;
|
||||
this.$element.removeClass('editable-disabled');
|
||||
@ -106,6 +121,10 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Disables editable
|
||||
@method disable()
|
||||
**/
|
||||
disable: function() {
|
||||
this.options.disabled = true;
|
||||
this.hide();
|
||||
@ -117,6 +136,10 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Toggles enabled / disabled state of editable element
|
||||
@method toggleDisabled()
|
||||
**/
|
||||
toggleDisabled: function() {
|
||||
if(this.options.disabled) {
|
||||
this.enable();
|
||||
@ -125,6 +148,13 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Sets new option
|
||||
|
||||
@method option(key, value)
|
||||
@param {string} key
|
||||
@param {mixed} value
|
||||
**/
|
||||
option: function(key, value) {
|
||||
if(key === 'disabled') {
|
||||
if(value) {
|
||||
@ -143,7 +173,7 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
/*
|
||||
* set emptytext if element is empty (reverse: remove emptytext if needed)
|
||||
*/
|
||||
handleEmpty: function () {
|
||||
@ -175,8 +205,9 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* show container with form
|
||||
*/
|
||||
Shows container with form
|
||||
@method show()
|
||||
**/
|
||||
show: function () {
|
||||
if(this.options.disabled) {
|
||||
return;
|
||||
@ -206,8 +237,9 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* hide container with form
|
||||
*/
|
||||
Hides container with form
|
||||
@method hide()
|
||||
**/
|
||||
hide: function () {
|
||||
if(this.container && this.container.tip().is(':visible')) {
|
||||
this.container.hide();
|
||||
@ -220,8 +252,9 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* show/hide form container
|
||||
*/
|
||||
Toggles container visibility (show / hide)
|
||||
@method toggle()
|
||||
**/
|
||||
toggle: function () {
|
||||
if(this.container && this.container.tip().is(':visible')) {
|
||||
this.hide();
|
||||
@ -230,7 +263,7 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
/*
|
||||
* called when form was submitted
|
||||
*/
|
||||
save: function(e, params) {
|
||||
@ -253,6 +286,26 @@
|
||||
|
||||
this.hide();
|
||||
this.setValue(params.newValue);
|
||||
|
||||
/**
|
||||
Fired when new value was submitted. You can use <code>$(this).data('editable')</code> inside handler to access to editable instance
|
||||
|
||||
@event save
|
||||
@param {Object} event event object
|
||||
@param {Object} params additional params
|
||||
@param {mixed} params.newValue submitted value
|
||||
@param {Object} params.response ajax response
|
||||
@example
|
||||
$('#username').on('save', function(e, params) {
|
||||
//assuming server response: '{success: true}'
|
||||
var pk = $(this).data('editable').options.pk;
|
||||
if(params.response && params.response.success) {
|
||||
alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!');
|
||||
} else {
|
||||
alert('error!');
|
||||
}
|
||||
});
|
||||
**/
|
||||
},
|
||||
|
||||
validate: function () {
|
||||
@ -261,11 +314,17 @@
|
||||
}
|
||||
},
|
||||
|
||||
setValue: function(v, convertStr) {
|
||||
/**
|
||||
Sets new value of editable
|
||||
@method setValue(value, convertStr)
|
||||
@param {mixed} value new value
|
||||
@param {boolean} convertStr wether to convert value from string to internal format
|
||||
**/
|
||||
setValue: function(value, convertStr) {
|
||||
if(convertStr) {
|
||||
this.value = this.input.str2value(v);
|
||||
this.value = this.input.str2value(value);
|
||||
} else {
|
||||
this.value = v;
|
||||
this.value = value;
|
||||
}
|
||||
if(this.container) {
|
||||
this.container.option('value', this.value);
|
||||
@ -281,10 +340,35 @@
|
||||
/* EDITABLE PLUGIN DEFINITION
|
||||
* ======================= */
|
||||
|
||||
/**
|
||||
jQuery method to initialize editable element.
|
||||
|
||||
@method $().editable(options)
|
||||
@params {Object} options
|
||||
@example
|
||||
$('#username').editable({
|
||||
type: 'text',
|
||||
url: 'post.php',
|
||||
pk: 1
|
||||
});
|
||||
**/
|
||||
$.fn.editable = function (option) {
|
||||
//special methods returning non-jquery object
|
||||
//special API methods returning non-jquery object
|
||||
var result = {}, args = arguments, datakey = 'editable';
|
||||
switch (option) {
|
||||
/**
|
||||
Runs client-side validation for all matched editables
|
||||
|
||||
@method validate()
|
||||
@returns {Object} validation errors map
|
||||
@example
|
||||
$('#username, #fullname').editable('validate');
|
||||
// possible result:
|
||||
{
|
||||
username: "username is requied",
|
||||
fullname: "fullname should be minimum 3 letters length"
|
||||
}
|
||||
**/
|
||||
case 'validate':
|
||||
this.each(function () {
|
||||
var $this = $(this), data = $this.data(datakey), error;
|
||||
@ -294,6 +378,18 @@
|
||||
});
|
||||
return result;
|
||||
|
||||
/**
|
||||
Returns current values of editable elements. If value is <code>null</code> or <code>undefined</code> it will not be returned
|
||||
@method getValue()
|
||||
@returns {Object} object of element names and values
|
||||
@example
|
||||
$('#username, #fullname').editable('validate');
|
||||
// possible result:
|
||||
{
|
||||
username: "superuser",
|
||||
fullname: "John"
|
||||
}
|
||||
**/
|
||||
case 'getValue':
|
||||
this.each(function () {
|
||||
var $this = $(this), data = $this.data(datakey);
|
||||
@ -303,6 +399,18 @@
|
||||
});
|
||||
return result;
|
||||
|
||||
/**
|
||||
This method collects values from several editable elements and submit them all to server.
|
||||
It is designed mainly for <a href="#newrecord">creating new records</a>.
|
||||
|
||||
@method submit(options)
|
||||
@param {object} options
|
||||
@param {object} options.url url to submit data
|
||||
@param {object} options.data additional data to submit
|
||||
@param {function} options.error(obj) error handler (called on both client-side and server-side validation errors)
|
||||
@param {function} options.success(obj) success handler
|
||||
@returns {Object} jQuery object
|
||||
**/
|
||||
case 'submit': //collects value, validate and submit to server for creating new record
|
||||
var config = arguments[1] || {},
|
||||
$elems = this,
|
||||
@ -360,14 +468,87 @@
|
||||
|
||||
|
||||
$.fn.editable.defaults = {
|
||||
type:'text',
|
||||
/**
|
||||
Type of input. Can be <code>text|textarea|select|date</code>
|
||||
|
||||
@property type
|
||||
@type string
|
||||
@default 'text'
|
||||
**/
|
||||
type: 'text',
|
||||
/**
|
||||
Sets disabled state of editable
|
||||
|
||||
@property disabled
|
||||
@type boolean
|
||||
@default false
|
||||
**/
|
||||
disabled: false,
|
||||
/**
|
||||
How to toggle editable. Can be <code>click|manual</code>.
|
||||
When set to <code>manual</code> you should manually call <code>show/hide</code> methods of editable.
|
||||
Note: if you are calling <code>show</code> on **click** event you need to apply <code>e.stopPropagation()</code> because container has behavior to hide on any click outside.
|
||||
|
||||
@example
|
||||
$('#edit-button').click(function(e) {
|
||||
e.stopPropagation();
|
||||
$('#username').editable('toggle');
|
||||
});
|
||||
|
||||
@property toggle
|
||||
@type string
|
||||
@default 'click'
|
||||
**/
|
||||
toggle: 'click',
|
||||
trigger: 'manual',
|
||||
/**
|
||||
Text shown when element is empty.
|
||||
|
||||
@property emptytext
|
||||
@type string
|
||||
@default 'Empty'
|
||||
**/
|
||||
emptytext: 'Empty',
|
||||
/**
|
||||
Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Usefull for select and date.
|
||||
For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>.
|
||||
<code>auto</code> - text will be automatically set only if element is empty.
|
||||
<code>always|never</code> - always(never) try to set element's text.
|
||||
|
||||
@property autotext
|
||||
@type string
|
||||
@default 'auto'
|
||||
**/
|
||||
autotext: 'auto',
|
||||
/**
|
||||
Wether to return focus on element after form is closed.
|
||||
This allows fully keyboard input.
|
||||
|
||||
@property enablefocus
|
||||
@type boolean
|
||||
@default false
|
||||
**/
|
||||
enablefocus: false,
|
||||
success: function(response, newValue) {} //value successfully sent on server and response status = 200
|
||||
/**
|
||||
Initial value of input
|
||||
|
||||
@property value
|
||||
@type mixed
|
||||
@default element's text
|
||||
**/
|
||||
value: null,
|
||||
/**
|
||||
Success callback. Called when value successfully sent on server and response status = 200.
|
||||
Can be used to process json response. If this function returns string - means error occured and string is shown as error message.
|
||||
|
||||
@property success
|
||||
@type function
|
||||
@default null
|
||||
@example
|
||||
success: function(response, newValue) {
|
||||
if(!response.success) return response.msg;
|
||||
}
|
||||
**/
|
||||
success: function(response, newValue) {}
|
||||
};
|
||||
|
||||
}(window.jQuery));
|
@ -1,16 +1,19 @@
|
||||
/**
|
||||
* editable abstract type definition
|
||||
* Every new type must implement this interface
|
||||
* It does not store value or text. It just store settings and input
|
||||
*/
|
||||
Abstract editable input class.
|
||||
To create your own input you should inherit from this class.
|
||||
|
||||
@class abstract
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var Abstract = function () { };
|
||||
|
||||
Abstract.prototype = {
|
||||
/**
|
||||
* initialize settings
|
||||
*/
|
||||
Iinitializes input
|
||||
|
||||
@method init()
|
||||
**/
|
||||
init: function(type, options, defaults) {
|
||||
this.type = type;
|
||||
this.options = $.extend({}, defaults, options);
|
||||
@ -19,9 +22,10 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* creates DOM element which is ready to be shown
|
||||
* Can return jQuery deferred object
|
||||
*/
|
||||
Renders input. Can return jQuery deferred object.
|
||||
|
||||
@method render()
|
||||
**/
|
||||
render: function() {
|
||||
this.$input = $(this.options.tpl);
|
||||
if(this.options.inputclass) {
|
||||
@ -34,51 +38,74 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* set element's html by value
|
||||
*/
|
||||
Sets element's html by value.
|
||||
|
||||
@method value2html(value, element)
|
||||
@param {mixed} value
|
||||
@param {DOMElement} element
|
||||
**/
|
||||
value2html: function(value, element) {
|
||||
var html = $('<div>').text(value).html();
|
||||
$(element).html(html);
|
||||
},
|
||||
|
||||
/**
|
||||
* returns value from element's html
|
||||
*/
|
||||
Converts element's html to value
|
||||
|
||||
@method html2value(html)
|
||||
@param {string} html
|
||||
@returns {mixed}
|
||||
**/
|
||||
html2value: function(html) {
|
||||
return $('<div>').html(html).text();
|
||||
},
|
||||
|
||||
/**
|
||||
* convert value to string for submiting on server
|
||||
*/
|
||||
Converts value to string (for submiting to server)
|
||||
|
||||
@method value2str(value)
|
||||
@param {mixed} value
|
||||
@returns {string}
|
||||
**/
|
||||
value2str: function(value) {
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* convert string received from server (data-value or options.value) into value object
|
||||
*/
|
||||
Converts string received from server into value.
|
||||
|
||||
@method str2value(str)
|
||||
@param {string} str
|
||||
@returns {mixed}
|
||||
**/
|
||||
str2value: function(str) {
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* set value to input
|
||||
*/
|
||||
Sets value of input.
|
||||
|
||||
@method value2input(value)
|
||||
@param {mixed} value
|
||||
**/
|
||||
value2input: function(value) {
|
||||
this.$input.val(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* returns value (object) by input
|
||||
*/
|
||||
Returns value of input. Value can be object (e.g. datepicker)
|
||||
|
||||
@method input2value()
|
||||
**/
|
||||
input2value: function() {
|
||||
return this.$input.val();
|
||||
},
|
||||
|
||||
/**
|
||||
* method called to focus input again
|
||||
*/
|
||||
Activates input. For text it sets focus.
|
||||
|
||||
@method activate()
|
||||
**/
|
||||
activate: function() {
|
||||
if(this.$input.is(':visible')) {
|
||||
this.$input.focus();
|
||||
@ -86,11 +113,31 @@
|
||||
}
|
||||
};
|
||||
|
||||
Abstract.defaults = {
|
||||
Abstract.defaults = {
|
||||
/**
|
||||
HTML template of input. Normally you should not change it.
|
||||
|
||||
@property tpl
|
||||
@type string
|
||||
@default ''
|
||||
**/
|
||||
tpl: '',
|
||||
/**
|
||||
CSS class automatically applied to input
|
||||
|
||||
@property inputclass
|
||||
@type string
|
||||
@default span2
|
||||
**/
|
||||
inputclass: 'span2',
|
||||
name: null,
|
||||
placeholder: false
|
||||
/**
|
||||
Name attribute of input
|
||||
|
||||
@property name
|
||||
@type string
|
||||
@default null
|
||||
**/
|
||||
name: null
|
||||
};
|
||||
|
||||
$.extend($.fn.editableform.types, {abstract: Abstract});
|
||||
|
62
src/inputs/date/datepicker.css → src/inputs/date/bootstrap-datepicker/css/datepicker.css
vendored
@ -72,9 +72,12 @@
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
/* vitalets: required to disable css inheritance when display inline inside table */
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.datepicker td.day:hover {
|
||||
background: #eeeeee;
|
||||
background: #eeeeee !important; /* disable inheritance for inline */
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker td.old,
|
||||
@ -87,11 +90,60 @@
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
}
|
||||
.datepicker td.today,
|
||||
.datepicker td.today:hover,
|
||||
.datepicker td.today.disabled,
|
||||
.datepicker td.today.disabled:hover {
|
||||
background-color: #fde19a !important; /* disable inheritance for inline */
|
||||
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
||||
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
||||
border-color: #fdf59a #fdf59a #fbed50;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
|
||||
}
|
||||
.datepicker td.today:hover,
|
||||
.datepicker td.today:hover:hover,
|
||||
.datepicker td.today.disabled:hover,
|
||||
.datepicker td.today.disabled:hover:hover,
|
||||
.datepicker td.today:active,
|
||||
.datepicker td.today:hover:active,
|
||||
.datepicker td.today.disabled:active,
|
||||
.datepicker td.today.disabled:hover:active,
|
||||
.datepicker td.today.active,
|
||||
.datepicker td.today:hover.active,
|
||||
.datepicker td.today.disabled.active,
|
||||
.datepicker td.today.disabled:hover.active,
|
||||
.datepicker td.today.disabled,
|
||||
.datepicker td.today:hover.disabled,
|
||||
.datepicker td.today.disabled.disabled,
|
||||
.datepicker td.today.disabled:hover.disabled,
|
||||
.datepicker td.today[disabled],
|
||||
.datepicker td.today:hover[disabled],
|
||||
.datepicker td.today.disabled[disabled],
|
||||
.datepicker td.today.disabled:hover[disabled] {
|
||||
background-color: #fdf59a !important; /* disable inheritance for inline */
|
||||
}
|
||||
.datepicker td.today:active,
|
||||
.datepicker td.today:hover:active,
|
||||
.datepicker td.today.disabled:active,
|
||||
.datepicker td.today.disabled:hover:active,
|
||||
.datepicker td.today.active,
|
||||
.datepicker td.today:hover.active,
|
||||
.datepicker td.today.disabled.active,
|
||||
.datepicker td.today.disabled:hover.active {
|
||||
background-color: #fbf069 \9;
|
||||
}
|
||||
.datepicker td.active,
|
||||
.datepicker td.active:hover,
|
||||
.datepicker td.active.disabled,
|
||||
.datepicker td.active.disabled:hover {
|
||||
background-color: #006dcc;
|
||||
background-color: #006dcc !important; /* disable inheritance for inline */
|
||||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||
@ -216,10 +268,12 @@
|
||||
.datepicker th.switch {
|
||||
width: 145px;
|
||||
}
|
||||
.datepicker thead tr:first-child th {
|
||||
.datepicker thead tr:first-child th,
|
||||
.datepicker tfoot tr:first-child th {
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker thead tr:first-child th:hover {
|
||||
.datepicker thead tr:first-child th:hover,
|
||||
.datepicker tfoot tr:first-child th:hover {
|
||||
background: #eeeeee;
|
||||
}
|
||||
.input-append.date .add-on i,
|
@ -1,14 +1,32 @@
|
||||
/**
|
||||
* date
|
||||
* based on fork: https://github.com/vitalets/bootstrap-datepicker
|
||||
*/
|
||||
Bootstrap-datepicker.
|
||||
Description and examples: http://vitalets.github.com/bootstrap-datepicker.
|
||||
For localization you can include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales
|
||||
|
||||
@class date
|
||||
@extends abstract
|
||||
@example
|
||||
<a href="#" id="dob" data-type="date" data-pk="1" data-url="post.php" data-original-title="Select date">15/05/1984</a>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#dob').editable({
|
||||
format: 'yyyy-mm-dd',
|
||||
viewformat: 'dd/mm/yyyy',
|
||||
datepicker: {
|
||||
weekStart: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var Date = function (options) {
|
||||
this.init('date', options, Date.defaults);
|
||||
|
||||
//set popular options directly from settings or data-* attributes
|
||||
var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format', 'weekStart', 'startView']);
|
||||
var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format']);
|
||||
|
||||
//overriding datepicker config (as by default jQuery extend() is not recursive)
|
||||
this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker);
|
||||
@ -68,15 +86,50 @@
|
||||
});
|
||||
|
||||
Date.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
tpl:'<div style="float: left; padding: 0; margin: 0 0 9px 0"></div>',
|
||||
inputclass: 'well',
|
||||
format:'yyyy-mm-dd', //format used for sending to server and converting from value
|
||||
viewformat: null, //used for display date in element
|
||||
//special options
|
||||
weekStart: 0,
|
||||
startView: 0,
|
||||
/**
|
||||
@property tpl
|
||||
@default <div></div>
|
||||
**/
|
||||
tpl:'<div></div>',
|
||||
/**
|
||||
@property inputclass
|
||||
@default editable-date well
|
||||
**/
|
||||
inputclass: 'editable-date well',
|
||||
/**
|
||||
Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br>
|
||||
Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code>
|
||||
|
||||
@property format
|
||||
@type string
|
||||
@default yyyy-mm-dd
|
||||
**/
|
||||
format:'yyyy-mm-dd',
|
||||
/**
|
||||
Format used for displaying date. Also applied when converting date from element's text on init.
|
||||
If not specified equals to <code>format</code>
|
||||
|
||||
@property viewformat
|
||||
@type string
|
||||
@default null
|
||||
**/
|
||||
viewformat: null,
|
||||
/**
|
||||
Configuration of datepicker.
|
||||
Full list of options: http://vitalets.github.com/bootstrap-datepicker
|
||||
|
||||
@property datepicker
|
||||
@type object
|
||||
@default {
|
||||
weekStart: 0,
|
||||
startView: 0,
|
||||
autoclose: false
|
||||
}
|
||||
**/
|
||||
datepicker:{
|
||||
autoclose:false
|
||||
weekStart: 0,
|
||||
startView: 0,
|
||||
autoclose: false
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,14 +1,32 @@
|
||||
/**
|
||||
* jQuery UI Datepicker
|
||||
* Note: you can not use both date and dateui on the one page!
|
||||
*/
|
||||
jQuery UI Datepicker.
|
||||
Description and examples: http://jqueryui.com/datepicker.
|
||||
Do not use it together with bootstrap-datepicker.
|
||||
|
||||
@class dateui
|
||||
@extends abstract
|
||||
@example
|
||||
<a href="#" id="dob" data-type="date" data-pk="1" data-url="post.php" data-original-title="Select date">15/05/1984</a>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#dob').editable({
|
||||
format: 'yyyy-mm-dd',
|
||||
viewformat: 'dd/mm/yyyy',
|
||||
datepicker: {
|
||||
firstDay: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var DateUI = function (options) {
|
||||
this.init('dateui', options, DateUI.defaults);
|
||||
|
||||
//set popular options directly from settings or data-* attributes
|
||||
var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format', 'firstDay']);
|
||||
var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format']);
|
||||
|
||||
//overriding datepicker config (as by default jQuery extend() is not recursive)
|
||||
this.options.datepicker = $.extend({}, DateUI.defaults.datepicker, directOptions, options.datepicker);
|
||||
@ -86,14 +104,49 @@
|
||||
});
|
||||
|
||||
DateUI.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
tpl:'<div style="float: left"></div>',
|
||||
inputclass: '',
|
||||
format:'yyyy-mm-dd', //format used for sending to server and converting from value
|
||||
viewformat: null, //used for display date in element
|
||||
/**
|
||||
@property tpl
|
||||
@default <div></div>
|
||||
**/
|
||||
tpl:'<div></div>',
|
||||
/**
|
||||
@property inputclass
|
||||
@default 'editable-date'
|
||||
**/
|
||||
inputclass: 'editable-date',
|
||||
/**
|
||||
Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br>
|
||||
Full list of tokens: http://docs.jquery.com/UI/Datepicker/formatDate
|
||||
|
||||
//special options
|
||||
firstDay: 0,
|
||||
datepicker:{
|
||||
@property format
|
||||
@type string
|
||||
@default yyyy-mm-dd
|
||||
**/
|
||||
format:'yyyy-mm-dd',
|
||||
/**
|
||||
Format used for displaying date. Also applied when converting date from element's text on init.
|
||||
If not specified equals to <code>format</code>
|
||||
|
||||
@property viewformat
|
||||
@type string
|
||||
@default null
|
||||
**/
|
||||
viewformat: null,
|
||||
|
||||
/**
|
||||
Configuration of datepicker.
|
||||
Full list of options: http://api.jqueryui.com/datepicker
|
||||
|
||||
@property datepicker
|
||||
@type object
|
||||
@default {
|
||||
firstDay: 0,
|
||||
changeYear: true,
|
||||
changeMonth: true
|
||||
}
|
||||
**/
|
||||
datepicker: {
|
||||
firstDay: 0,
|
||||
changeYear: true,
|
||||
changeMonth: true
|
||||
}
|
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png
Normal file
After ![]() (image error) Size: 180 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png
Normal file
After ![]() (image error) Size: 182 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png
Normal file
After ![]() (image error) Size: 162 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png
Normal file
After ![]() (image error) Size: 123 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png
Normal file
After ![]() (image error) Size: 119 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
Normal file
After ![]() (image error) Size: 3.4 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
Normal file
After ![]() (image error) Size: 104 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
Normal file
After ![]() (image error) Size: 88 B |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_217bc0_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_2e83ff_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_469bdd_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_6da8d5_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_cd0a0a_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_d8e7f3_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
BIN
src/inputs/dateui/jquery-ui-datepicker/css/redmond/images/ui-icons_f9bd01_256x240.png
Normal file
After ![]() (image error) Size: 4.3 KiB |
461
src/inputs/dateui/jquery-ui-datepicker/css/redmond/jquery-ui-1.9.1.custom.css
vendored
Normal file
@ -0,0 +1,461 @@
|
||||
/*! jQuery UI - v1.9.1 - 2012-11-05
|
||||
* http://jqueryui.com
|
||||
* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||
* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
|
||||
|
||||
/* Layout helpers
|
||||
----------------------------------*/
|
||||
.ui-helper-hidden { display: none; }
|
||||
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
||||
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
||||
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
|
||||
.ui-helper-clearfix:after { clear: both; }
|
||||
.ui-helper-clearfix { zoom: 1; }
|
||||
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
||||
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-disabled { cursor: default !important; }
|
||||
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||
.ui-resizable { position: relative;}
|
||||
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||
.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
|
||||
.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
|
||||
.ui-autocomplete {
|
||||
position: absolute;
|
||||
top: 0; /* #8656 */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* workarounds */
|
||||
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
||||
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
||||
.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
|
||||
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
||||
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
||||
.ui-button-icons-only { width: 3.4em; }
|
||||
button.ui-button-icons-only { width: 3.7em; }
|
||||
|
||||
/*button text element */
|
||||
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
||||
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
||||
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
||||
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
||||
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
||||
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
||||
/* no icon support for input elements, provide padding by default */
|
||||
input.ui-button { padding: .4em 1em; }
|
||||
|
||||
/*button icon element(s) */
|
||||
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
||||
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
||||
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
||||
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
|
||||
/*button sets*/
|
||||
.ui-buttonset { margin-right: 7px; }
|
||||
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
||||
|
||||
/* workarounds */
|
||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
||||
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||
.ui-datepicker td { border: 0; padding: 1px; }
|
||||
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||
|
||||
/* with multiple calendars */
|
||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
||||
|
||||
/* RTL support */
|
||||
.ui-datepicker-rtl { direction: rtl; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
|
||||
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||
.ui-datepicker-cover {
|
||||
position: absolute; /*must have*/
|
||||
z-index: -1; /*must have*/
|
||||
filter: mask(); /*must have*/
|
||||
top: -4px; /*must have*/
|
||||
left: -4px; /*must have*/
|
||||
width: 200px; /*must have*/
|
||||
height: 200px; /*must have*/
|
||||
}.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
||||
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
||||
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
|
||||
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
|
||||
.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
|
||||
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
||||
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
||||
.ui-menu .ui-menu-item a.ui-state-focus,
|
||||
.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
|
||||
|
||||
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
|
||||
.ui-menu .ui-state-disabled a { cursor: default; }
|
||||
|
||||
/* icon support */
|
||||
.ui-menu-icons { position: relative; }
|
||||
.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
|
||||
|
||||
/* left-aligned */
|
||||
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
|
||||
|
||||
/* right-aligned */
|
||||
.ui-menu .ui-menu-icon { position: static; float: right; }
|
||||
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
|
||||
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }.ui-slider { position: relative; text-align: left; }
|
||||
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
||||
|
||||
.ui-slider-horizontal { height: .8em; }
|
||||
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||
|
||||
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
|
||||
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
|
||||
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
|
||||
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
|
||||
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
|
||||
.ui-spinner-up { top: 0; }
|
||||
.ui-spinner-down { bottom: 0; }
|
||||
|
||||
/* TR overrides */
|
||||
.ui-spinner .ui-icon-triangle-1-s {
|
||||
/* need to fix icons sprite */
|
||||
background-position:-65px -16px;
|
||||
}
|
||||
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
||||
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
|
||||
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||
.ui-tooltip {
|
||||
padding: 8px;
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
max-width: 300px;
|
||||
-webkit-box-shadow: 0 0 5px #aaa;
|
||||
box-shadow: 0 0 5px #aaa;
|
||||
}
|
||||
/* Fades and background-images don't work well together in IE6, drop the image */
|
||||
* html .ui-tooltip {
|
||||
background-image: none;
|
||||
}
|
||||
body .ui-tooltip { border-width: 2px; }
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget { font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; font-size: 1.1em; }
|
||||
.ui-widget .ui-widget { font-size: 1em; }
|
||||
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; font-size: 1em; }
|
||||
.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
|
||||
.ui-widget-content a { color: #222222; }
|
||||
.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
|
||||
.ui-widget-header a { color: #ffffff; }
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; }
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; }
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; }
|
||||
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #1d5987; text-decoration: none; }
|
||||
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; }
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; text-decoration: none; }
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
|
||||
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
|
||||
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
|
||||
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
|
||||
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
|
||||
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
||||
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
||||
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
||||
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
|
||||
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
|
||||
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
|
||||
.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
|
||||
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
|
||||
.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
|
||||
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
|
||||
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
|
||||
|
||||
/* positioning */
|
||||
.ui-icon-carat-1-n { background-position: 0 0; }
|
||||
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
||||
.ui-icon-carat-1-e { background-position: -32px 0; }
|
||||
.ui-icon-carat-1-se { background-position: -48px 0; }
|
||||
.ui-icon-carat-1-s { background-position: -64px 0; }
|
||||
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
||||
.ui-icon-carat-1-w { background-position: -96px 0; }
|
||||
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
||||
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
||||
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
||||
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
||||
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
||||
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
||||
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||
.ui-icon-extlink { background-position: -32px -80px; }
|
||||
.ui-icon-newwin { background-position: -48px -80px; }
|
||||
.ui-icon-refresh { background-position: -64px -80px; }
|
||||
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||
.ui-icon-document { background-position: -32px -96px; }
|
||||
.ui-icon-document-b { background-position: -48px -96px; }
|
||||
.ui-icon-note { background-position: -64px -96px; }
|
||||
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||
.ui-icon-comment { background-position: -128px -96px; }
|
||||
.ui-icon-person { background-position: -144px -96px; }
|
||||
.ui-icon-print { background-position: -160px -96px; }
|
||||
.ui-icon-trash { background-position: -176px -96px; }
|
||||
.ui-icon-locked { background-position: -192px -96px; }
|
||||
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||
.ui-icon-tag { background-position: -240px -96px; }
|
||||
.ui-icon-home { background-position: 0 -112px; }
|
||||
.ui-icon-flag { background-position: -16px -112px; }
|
||||
.ui-icon-calendar { background-position: -32px -112px; }
|
||||
.ui-icon-cart { background-position: -48px -112px; }
|
||||
.ui-icon-pencil { background-position: -64px -112px; }
|
||||
.ui-icon-clock { background-position: -80px -112px; }
|
||||
.ui-icon-disk { background-position: -96px -112px; }
|
||||
.ui-icon-calculator { background-position: -112px -112px; }
|
||||
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||
.ui-icon-search { background-position: -160px -112px; }
|
||||
.ui-icon-wrench { background-position: -176px -112px; }
|
||||
.ui-icon-gear { background-position: -192px -112px; }
|
||||
.ui-icon-heart { background-position: -208px -112px; }
|
||||
.ui-icon-star { background-position: -224px -112px; }
|
||||
.ui-icon-link { background-position: -240px -112px; }
|
||||
.ui-icon-cancel { background-position: 0 -128px; }
|
||||
.ui-icon-plus { background-position: -16px -128px; }
|
||||
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||
.ui-icon-minus { background-position: -48px -128px; }
|
||||
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||
.ui-icon-close { background-position: -80px -128px; }
|
||||
.ui-icon-closethick { background-position: -96px -128px; }
|
||||
.ui-icon-key { background-position: -112px -128px; }
|
||||
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||
.ui-icon-scissors { background-position: -144px -128px; }
|
||||
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||
.ui-icon-copy { background-position: -176px -128px; }
|
||||
.ui-icon-contact { background-position: -192px -128px; }
|
||||
.ui-icon-image { background-position: -208px -128px; }
|
||||
.ui-icon-video { background-position: -224px -128px; }
|
||||
.ui-icon-script { background-position: -240px -128px; }
|
||||
.ui-icon-alert { background-position: 0 -144px; }
|
||||
.ui-icon-info { background-position: -16px -144px; }
|
||||
.ui-icon-notice { background-position: -32px -144px; }
|
||||
.ui-icon-help { background-position: -48px -144px; }
|
||||
.ui-icon-check { background-position: -64px -144px; }
|
||||
.ui-icon-bullet { background-position: -80px -144px; }
|
||||
.ui-icon-radio-on { background-position: -96px -144px; }
|
||||
.ui-icon-radio-off { background-position: -112px -144px; }
|
||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||
.ui-icon-play { background-position: 0 -160px; }
|
||||
.ui-icon-pause { background-position: -16px -160px; }
|
||||
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||
.ui-icon-seek-start { background-position: -80px -160px; }
|
||||
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
||||
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||
.ui-icon-stop { background-position: -96px -160px; }
|
||||
.ui-icon-eject { background-position: -112px -160px; }
|
||||
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||
.ui-icon-power { background-position: 0 -176px; }
|
||||
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||
.ui-icon-signal { background-position: -32px -176px; }
|
||||
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -khtml-border-top-left-radius: 5px; border-top-left-radius: 5px; }
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -khtml-border-top-right-radius: 5px; border-top-right-radius: 5px; }
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -khtml-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; -khtml-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
|
||||
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
|
5
src/inputs/dateui/jquery-ui-datepicker/css/redmond/jquery-ui-1.9.1.custom.min.css
vendored
Normal file
3454
src/inputs/dateui/jquery-ui-datepicker/js/jquery-ui-1.9.1.custom.js
vendored
Normal file
6
src/inputs/dateui/jquery-ui-datepicker/js/jquery-ui-1.9.1.custom.min.js
vendored
Normal file
@ -1,6 +1,24 @@
|
||||
/**
|
||||
* select
|
||||
*/
|
||||
Select (dropdown) input
|
||||
|
||||
@class select
|
||||
@extends abstract
|
||||
@example
|
||||
<a href="#" id="status" data-type="select" data-pk="1" data-url="post.php" data-original-title="Select status"></a>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#status').editable({
|
||||
value: 2,
|
||||
source: [
|
||||
{value: 1, text: 'Active'},
|
||||
{value: 2, text: 'Blocked'},
|
||||
{value: 3, text: 'Deleted'}
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var Select = function (options) {
|
||||
@ -28,13 +46,13 @@
|
||||
},
|
||||
|
||||
html2value: function (html) {
|
||||
return null; //it's not good idea to set value by text for SELECT. better set NULL
|
||||
return null; //it's not good idea to set value by text for SELECT. Better set NULL
|
||||
},
|
||||
|
||||
value2html: function (value, element) {
|
||||
var deferred = $.Deferred();
|
||||
this.onSourceReady(function () {
|
||||
var i, text = null;
|
||||
var i, text = '';
|
||||
if($.isArray(this.sourceData)) {
|
||||
for(i=0; i<this.sourceData.length; i++){
|
||||
/*jshint eqeqeq: false*/
|
||||
@ -213,12 +231,39 @@
|
||||
});
|
||||
|
||||
Select.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <select></select>
|
||||
**/
|
||||
tpl:'<select></select>',
|
||||
source:null, //can be string (url), object or array [{value: 1, text: 'abc'}, {...}]
|
||||
/**
|
||||
Source data for dropdown list. If string - considered ajax url to load items. Otherwise should be an array.
|
||||
Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br>
|
||||
For compability it also supports format <code>{value1: text1, value2: text2 ...}</code> but it does not guarantee elements order.
|
||||
|
||||
@property source
|
||||
@type string|array|object
|
||||
@default null
|
||||
**/
|
||||
source:null,
|
||||
/**
|
||||
Data automatically prepended to the begining of dropdown list.
|
||||
|
||||
@property prepend
|
||||
@type string|array|object
|
||||
@default false
|
||||
**/
|
||||
prepend:false,
|
||||
/**
|
||||
Error message shown when list cannot be loaded (e.g. ajax error)
|
||||
|
||||
@property sourceError
|
||||
@type string
|
||||
@default Error when loading options
|
||||
**/
|
||||
sourceError: 'Error when loading options'
|
||||
});
|
||||
|
||||
$.fn.editableform.types.select = Select;
|
||||
|
||||
}(window.jQuery));
|
||||
}(window.jQuery));
|
||||
|
@ -1,6 +1,19 @@
|
||||
/**
|
||||
* text
|
||||
*/
|
||||
Text input
|
||||
|
||||
@class text
|
||||
@extends abstract
|
||||
@example
|
||||
<a href="#" id="username" data-type="text" data-pk="1">awesome</a>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#username').editable({
|
||||
url: 'post.php',
|
||||
title: 'Enter username'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
**/
|
||||
(function ($) {
|
||||
var Text = function (options) {
|
||||
this.init('text', options, Text.defaults);
|
||||
@ -18,9 +31,21 @@
|
||||
});
|
||||
|
||||
Text.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
tpl: '<input type="text">'
|
||||
/**
|
||||
@property tpl
|
||||
@default <input type="text">
|
||||
**/
|
||||
tpl: '<input type="text">',
|
||||
/**
|
||||
Placeholder attribute of input. Shown when input is empty.
|
||||
|
||||
@property placeholder
|
||||
@type string
|
||||
@default null
|
||||
**/
|
||||
placeholder: null
|
||||
});
|
||||
|
||||
$.fn.editableform.types.text = Text;
|
||||
|
||||
}(window.jQuery));
|
||||
}(window.jQuery));
|
||||
|
@ -1,6 +1,19 @@
|
||||
/**
|
||||
* textarea
|
||||
*/
|
||||
Textarea input
|
||||
|
||||
@class textarea
|
||||
@extends abstract
|
||||
@example
|
||||
<a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#comments').editable({
|
||||
url: 'post.php',
|
||||
title: 'Enter comments'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var Textarea = function (options) {
|
||||
@ -53,8 +66,24 @@
|
||||
});
|
||||
|
||||
Textarea.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
tpl:'<textarea rows="8"></textarea>',
|
||||
inputclass:'span3'
|
||||
/**
|
||||
@property tpl
|
||||
@default <textarea></textarea>
|
||||
**/
|
||||
tpl:'<textarea></textarea>',
|
||||
/**
|
||||
@property inputclass
|
||||
@default span3
|
||||
**/
|
||||
inputclass:'span3',
|
||||
/**
|
||||
Placeholder attribute of input. Shown when input is empty.
|
||||
|
||||
@property placeholder
|
||||
@type string
|
||||
@default null
|
||||
**/
|
||||
placeholder: null
|
||||
});
|
||||
|
||||
$.fn.editableform.types.textarea = Textarea;
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Bootstrap Editable</title>
|
||||
<title>Test X-editable</title>
|
||||
|
||||
<!-- jquery -->
|
||||
<script src="../libs/jquery/jquery-1.8.2.js"></script>
|
||||
|
@ -54,7 +54,7 @@ function getAssets(f, c, src, libs) {
|
||||
js.push(getContainer('editable-tooltip.js'));
|
||||
|
||||
//date
|
||||
js.push(inputs+'dateui.js');
|
||||
js.push(inputs+'dateui/dateui.js');
|
||||
|
||||
//style
|
||||
css.push('style.css');
|
||||
@ -67,9 +67,9 @@ function getAssets(f, c, src, libs) {
|
||||
js.push(getContainer('editable-poshytip.js'));
|
||||
|
||||
//date
|
||||
js.push(inputs+'dateui.js');
|
||||
js.push(libs+'jquery-ui-datepicker/js/jquery-ui-1.9.1.custom.js');
|
||||
css.unshift(jqueryui+'css/redmond/jquery-ui-1.9.1.custom.css');
|
||||
js.push(inputs+'dateui/dateui.js');
|
||||
js.push(inputs+'dateui/jquery-ui-datepicker/js/jquery-ui-1.9.1.custom.js');
|
||||
css.unshift(inputs+'dateui/jquery-ui-datepicker/css/smoothness/jquery-ui-1.9.1.custom.css');
|
||||
|
||||
//style
|
||||
css.push('style.css');
|
||||
@ -83,9 +83,9 @@ function getAssets(f, c, src, libs) {
|
||||
js.push(getContainer('editable-popover.js'));
|
||||
|
||||
//date
|
||||
js.push(inputs+'date/bootstrap-datepicker.js');
|
||||
js.push(inputs+'date/bootstrap-datepicker/js/bootstrap-datepicker.js');
|
||||
js.push(inputs+'date/date.js');
|
||||
css.push(inputs+'date/datepicker.css');
|
||||
css.push(inputs+'date/bootstrap-datepicker/css/datepicker.css');
|
||||
}
|
||||
|
||||
function getContainer(container) {
|
||||
|
@ -83,6 +83,8 @@
|
||||
if(!$.browser.webkit && fc.f !== 'jqueryui') {
|
||||
ok(p.offset().top > e.offset().top, 'placement ok');
|
||||
}
|
||||
|
||||
//check title
|
||||
ok(p.find(':contains("'+title+'")').length, 'title ok');
|
||||
e.remove();
|
||||
});
|
||||
|
@ -16,8 +16,11 @@ $(function () {
|
||||
|
||||
asyncTest("popover should contain datepicker with value and save new entered date", function () {
|
||||
expect(9);
|
||||
|
||||
$.fn.editableform.types.date.defaults.datepicker.weekStart = 1;
|
||||
|
||||
var d = '15.05.1984',
|
||||
e = $('<a href="#" data-type="date" data-pk="1" data-weekstart="1" data-url="post-date.php">'+d+'</a>').appendTo(fx).editable({
|
||||
e = $('<a href="#" data-type="date" data-pk="1" data-url="post-date.php">'+d+'</a>').appendTo(fx).editable({
|
||||
format: f,
|
||||
datepicker: {
|
||||
|
||||
@ -57,9 +60,12 @@ $(function () {
|
||||
});
|
||||
|
||||
asyncTest("viewformat, init by text", function () {
|
||||
|
||||
$.fn.editableform.types.date.defaults.datepicker.weekStart = 1;
|
||||
|
||||
var dview = '15/05/1984',
|
||||
d = '1984-05-15',
|
||||
e = $('<a href="#" data-type="date" data-pk="1" data-weekstart="1" data-url="post-date1.php">'+dview+'</a>').appendTo(fx).editable({
|
||||
e = $('<a href="#" data-type="date" data-pk="1" data-url="post-date1.php">'+dview+'</a>').appendTo(fx).editable({
|
||||
format: 'yyyy-mm-dd',
|
||||
viewformat: 'dd/mm/yyyy',
|
||||
datepicker: {
|
||||
|
@ -20,7 +20,9 @@ $(function () {
|
||||
e = $('<a href="#" data-type="date" data-pk="1" data-url="post-date.php">'+dview+'</a>').appendTo(fx).editable({
|
||||
format: 'dd.mm.yyyy',
|
||||
viewformat: 'dd/mm/yyyy',
|
||||
firstDay: 1
|
||||
datepicker: {
|
||||
firstDay: 1
|
||||
}
|
||||
}),
|
||||
nextD = '16.05.1984',
|
||||
nextDview = '16/05/1984';
|
||||
|
@ -9,11 +9,15 @@ $(function () {
|
||||
5: 'Admin',
|
||||
6: '',
|
||||
'': 'Nothing'
|
||||
};
|
||||
};
|
||||
|
||||
window.size = 0;
|
||||
//groups as array
|
||||
window.groupsArr = [];
|
||||
for(var i in groups) {
|
||||
groupsArr.push({value: i, text: groups[i]});
|
||||
}
|
||||
|
||||
for (e in groups) { size++; }
|
||||
window.size = groupsArr.length;
|
||||
|
||||
$.mockjax({
|
||||
url: 'groups.php',
|
||||
@ -86,7 +90,25 @@ $(function () {
|
||||
ok(!p.is(':visible'), 'popover was removed');
|
||||
});
|
||||
|
||||
test("load options from native array", function () {
|
||||
test("load options from normal array", function () {
|
||||
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo('#qunit-fixture').editable({
|
||||
pk: 1,
|
||||
source: groupsArr,
|
||||
placement: 'right'
|
||||
});
|
||||
|
||||
e.click()
|
||||
var p = tip(e);
|
||||
ok(p.is(':visible'), 'popover visible');
|
||||
ok(p.find('select').length, 'select exists');
|
||||
equal(p.find('select').find('option').length, groupsArr.length, 'options loaded');
|
||||
equal(p.find('select').val(), e.data('editable').value, 'selected value correct');
|
||||
|
||||
p.find('button[type=button]').click();
|
||||
ok(!p.is(':visible'), 'popover was removed');
|
||||
});
|
||||
|
||||
test("load options from simple array", function () {
|
||||
var arr = ['q', 'w', 'x'],
|
||||
e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo('#qunit-fixture').editable({
|
||||
pk: 1,
|
||||
|
@ -240,7 +240,33 @@ $(function () {
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
asyncTest("submit to url defined as function", function () {
|
||||
expect(3);
|
||||
var newText = 'qwe',
|
||||
e = $('<a href="#" data-pk="1" id="a"></a>').appendTo(fx).editable({
|
||||
url: function(params) {
|
||||
ok(params.value, newText, 'new text passed in users function');
|
||||
var d = new $.Deferred;
|
||||
return d.reject('my error');
|
||||
}
|
||||
});
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
|
||||
ok(p.find('input[type=text]').length, 'input exists')
|
||||
p.find('input').val(newText);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
equal(p.find('.editable-error-block').text(), 'my error', 'error shown correctly');
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
asyncTest("should show emptytext if entered text is empty", function () {
|
||||
var emptytext = 'blabla',
|
||||
|