Compare commits
No commits in common. "ci" and "4.0" have entirely different histories.
|
@ -1,64 +0,0 @@
|
|||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref_name:
|
||||
description: 'Tag or commit'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build-tarball:
|
||||
name: Build tarball w/ submodules
|
||||
runs-on: x86_64
|
||||
container:
|
||||
image: alpine:latest
|
||||
env:
|
||||
CI_PROJECT_NAME: zotero
|
||||
steps:
|
||||
- name: Environment setup
|
||||
run: apk add nodejs git git-archive-all gzip
|
||||
- name: Repo pull
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 500
|
||||
ref: ${{ inputs.ref_name }}
|
||||
- name: Package build
|
||||
run: |
|
||||
if test $GITHUB_REF_NAME == "ci" ; then
|
||||
CI_REF_NAME=${{ inputs.ref_name }}
|
||||
else
|
||||
CI_REF_NAME=$GITHUB_REF_NAME
|
||||
fi
|
||||
echo "building tarball for $CI_REF_NAME"
|
||||
git-archive-all --force-submodules $CI_PROJECT_NAME-$CI_REF_NAME.tar.gz
|
||||
echo "Generating sha512sum"
|
||||
sha512sum $CI_PROJECT_NAME-$CI_REF_NAME.tar.gz > $CI_PROJECT_NAME-$CI_REF_NAME.tar.gz.sha512sum
|
||||
- name: Package upload
|
||||
uses: forgejo/upload-artifact@v3
|
||||
with:
|
||||
name: tarball
|
||||
path: zotero-*.tar*
|
||||
upload-tarball:
|
||||
name: Upload to generic repo
|
||||
runs-on: x86_64
|
||||
needs: [build-tarball]
|
||||
container:
|
||||
image: alpine:latest
|
||||
steps:
|
||||
- name: Environment setup
|
||||
run: apk add nodejs curl
|
||||
- name: Package download
|
||||
uses: forgejo/download-artifact@v3
|
||||
- name: Package deployment
|
||||
run: |
|
||||
if test $GITHUB_REF_NAME == "ci" ; then
|
||||
CI_REF_NAME=${{ inputs.ref_name }}
|
||||
else
|
||||
CI_REF_NAME=$GITHUB_REF_NAME
|
||||
fi
|
||||
curl --user ${{ vars.CODE_FORGEJO_USER }}:${{ secrets.CODE_FORGEJO_TOKEN }} --upload-file ./tarball/zotero-*.tar.gz ${{ github.server_url }}/api/packages/mirrors/generic/zotero/$CI_REF_NAME/zotero-$CI_REF_NAME.tar.gz
|
||||
curl --user ${{ vars.CODE_FORGEJO_USER }}:${{ secrets.CODE_FORGEJO_TOKEN }} --upload-file ./tarball/zotero-*.tar.gz.sha512sum ${{ github.server_url }}/api/packages/mirrors/generic/zotero/$CI_REF_NAME/zotero-$CI_REF_NAME.tar.gz.sha512sum
|
|
@ -1,50 +0,0 @@
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
schedule:
|
||||
- cron: '@hourly'
|
||||
|
||||
jobs:
|
||||
mirror:
|
||||
name: Pull from upstream
|
||||
runs-on: x86_64
|
||||
container:
|
||||
image: alpine:latest
|
||||
env:
|
||||
upstream: https://github.com/zotero/zotero
|
||||
tags: '7.*'
|
||||
steps:
|
||||
- name: Environment setup
|
||||
run: apk add grep git sed coreutils bash nodejs
|
||||
- name: Fetch destination
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch_depth: 1
|
||||
ref: ci
|
||||
token: ${{ secrets.CODE_FORGEJO_TOKEN }}
|
||||
- name: Missing tag detecting
|
||||
run: |
|
||||
git ls-remote $upstream "refs/tags/$tags" | grep -v '{' | sed 's|.*/||' > upstream_tags
|
||||
git ls-remote ${{ github.server_url}}/${{ github.repository }} "refs/tags/$tags" | grep -v '{' | sed 's|.*/||' > destination_tags
|
||||
cat upstream_tags destination_tags | tr ' ' '\n' | sort | uniq -u > missing_tags
|
||||
echo "Missing tags:"
|
||||
cat missing_tags
|
||||
- name: Missing tag fetch
|
||||
run: |
|
||||
git remote add upstream $upstream
|
||||
while read tag; do
|
||||
git fetch upstream tag $tag --no-tags
|
||||
done < missing_tags
|
||||
- name: Packaging workflow injection
|
||||
run: |
|
||||
while read tag; do
|
||||
git checkout $tag
|
||||
git tag -d $tag
|
||||
git checkout ci -- ./.forgejo
|
||||
git config user.name "forgejo-actions[bot]"
|
||||
git config user.email "dev@ayakael.net"
|
||||
git commit -m 'Inject custom workflow'
|
||||
git tag -a $tag -m $tag
|
||||
done < missing_tags
|
||||
- name: Push to destination
|
||||
run: git push --force origin refs/tags/*:refs/tags/* --tags
|
15
.gitmodules
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
[submodule "translators"]
|
||||
path = translators
|
||||
url = git://github.com/zotero/translators.git
|
||||
[submodule "chrome/content/zotero/locale/csl"]
|
||||
path = chrome/content/zotero/locale/csl
|
||||
url = git://github.com/citation-style-language/locales.git
|
||||
[submodule "styles"]
|
||||
path = styles
|
||||
url = git://github.com/zotero/bundled-styles.git
|
||||
[submodule "test/resource/chai"]
|
||||
path = test/resource/chai
|
||||
url = https://github.com/chaijs/chai.git
|
||||
[submodule "test/resource/mocha"]
|
||||
path = test/resource/mocha
|
||||
url = https://github.com/mochajs/mocha.git
|
30
.travis.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
sudo: false
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
env:
|
||||
- FX_CHANNEL="release"
|
||||
- FX_CHANNEL="beta"
|
||||
- FX_CHANNEL="esr"
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: FX_CHANNEL="-beta"
|
||||
notifications:
|
||||
email: false
|
||||
install:
|
||||
# Use unbranded builds for 'release' and 'beta'
|
||||
- if [ $FX_CHANNEL != "esr" ]; then
|
||||
URL="`curl -s https://wiki.mozilla.org/Addons/Extension_Signing | sed -n -r \"s/.+https?(:\/\/archive.mozilla.org[^ ]+\/mozilla-${FX_CHANNEL}-linux64-add-on-devel\/[0-9]+\/.+.bz2).+/https\1/p\"`";
|
||||
wget -O tarball "$URL";
|
||||
fi
|
||||
# Use official build for 'esr'
|
||||
- if [ $FX_CHANNEL == "esr" ]; then
|
||||
wget -O tarball "https://download.mozilla.org/?product=firefox-${FX_CHANNEL}-latest&os=linux64&lang=en-US";
|
||||
fi
|
||||
- tar xf tarball
|
||||
before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
script:
|
||||
- test/runtests.sh -x firefox/firefox
|
11
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Contributing to Zotero
|
||||
|
||||
## Bug Reports and Feature Requests
|
||||
|
||||
In order to keep product discussions open to as many people as possible, Zotero does not use GitHub Issues for bug reports or feature requests. Please use the [Zotero Forums](https://forums.zotero.org) to report problems and suggest changes.
|
||||
|
||||
For confirmed bugs or agreed-upon changes, new issues will be created in the relevant repositories on GitHub by Zotero developers.
|
||||
|
||||
## Working with Zotero Code
|
||||
|
||||
See [Zotero Source Code](https://www.zotero.org/support/dev/source_code).
|
678
COPYING
Normal file
|
@ -0,0 +1,678 @@
|
|||
Zotero is Copyright © 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Center for History and New Media, George Mason University,
|
||||
Fairfax, Virginia, USA http://zotero.org
|
||||
|
||||
The Center for History and New Media distributes the Zotero source code
|
||||
under the GNU Affero General Public License, version 3 (AGPLv3). The full text
|
||||
of this license is given below.
|
||||
|
||||
The Zotero name is a registered trademark of George Mason University.
|
||||
See http://zotero.org/trademark for more information.
|
||||
|
||||
Third-party copyright in this distribution is noted where applicable.
|
||||
|
||||
All rights not expressly granted are reserved.
|
||||
|
||||
=========================================================================
|
||||
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
9
README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
Zotero
|
||||
======
|
||||
[![Build Status](https://travis-ci.org/zotero/zotero.svg?branch=4.0)](https://travis-ci.org/zotero/zotero)
|
||||
|
||||
[Zotero](https://www.zotero.org/) is a free, easy-to-use tool to help you collect, organize, cite, and share your research sources.
|
||||
|
||||
Please post feature requests or bug reports to the [Zotero Forums](https://forums.zotero.org/). If you're having trouble with Zotero, see [Getting Help](https://www.zotero.org/support/getting_help).
|
||||
|
||||
For more information on how to use this source code, see the [Zotero wiki](https://www.zotero.org/support/dev/source_code).
|
84
chrome.manifest
Normal file
|
@ -0,0 +1,84 @@
|
|||
content zotero chrome/content/zotero/
|
||||
content zotero-platform chrome/content/zotero-platform/mac/ os=Darwin
|
||||
content zotero-platform chrome/content/zotero-platform/win/ os=WINNT
|
||||
content zotero-platform chrome/content/zotero-platform/unix/ os=Linux
|
||||
content zotero-platform chrome/content/zotero-platform/unix/ os=SunOS
|
||||
content zotero-platform chrome/content/zotero-platform/unix/ os=FreeBSD
|
||||
content zotero-platform chrome/content/zotero-platform/unix/ os=OpenBSD
|
||||
|
||||
resource zotero resource/
|
||||
|
||||
locale zotero en-US chrome/locale/en-US/zotero/
|
||||
locale zotero af-ZA chrome/locale/af-ZA/zotero/
|
||||
locale zotero ar chrome/locale/ar/zotero/
|
||||
locale zotero bg-BG chrome/locale/bg-BG/zotero/
|
||||
locale zotero ca-AD chrome/locale/ca-AD/zotero/
|
||||
locale zotero cs-CZ chrome/locale/cs-CZ/zotero/
|
||||
locale zotero da-DK chrome/locale/da-DK/zotero/
|
||||
locale zotero de chrome/locale/de/zotero/
|
||||
locale zotero el-GR chrome/locale/el-GR/zotero/
|
||||
locale zotero es-ES chrome/locale/es-ES/zotero/
|
||||
locale zotero et-EE chrome/locale/et-EE/zotero/
|
||||
locale zotero eu-ES chrome/locale/eu-ES/zotero/
|
||||
locale zotero fa chrome/locale/fa/zotero/
|
||||
locale zotero fi-FI chrome/locale/fi-FI/zotero/
|
||||
locale zotero fr-FR chrome/locale/fr-FR/zotero/
|
||||
locale zotero gl-ES chrome/locale/gl-ES/zotero/
|
||||
locale zotero he-IL chrome/locale/he-IL/zotero/
|
||||
locale zotero hr-HR chrome/locale/hr-HR/zotero/
|
||||
locale zotero hu-HU chrome/locale/hu-HU/zotero/
|
||||
locale zotero id-ID chrome/locale/id-ID/zotero/
|
||||
locale zotero is-IS chrome/locale/is-IS/zotero/
|
||||
locale zotero it-IT chrome/locale/it-IT/zotero/
|
||||
locale zotero ja-JP chrome/locale/ja-JP/zotero/
|
||||
locale zotero km chrome/locale/km/zotero/
|
||||
locale zotero ko-KR chrome/locale/ko-KR/zotero/
|
||||
locale zotero lt-LT chrome/locale/lt-LT/zotero/
|
||||
locale zotero mn-MN chrome/locale/mn-MN/zotero/
|
||||
locale zotero nb-NO chrome/locale/nb-NO/zotero/
|
||||
locale zotero nn-NO chrome/locale/nn-NO/zotero/
|
||||
locale zotero nl-NL chrome/locale/nl-NL/zotero/
|
||||
locale zotero pl-PL chrome/locale/pl-PL/zotero/
|
||||
locale zotero pt-BR chrome/locale/pt-BR/zotero/
|
||||
locale zotero pt-PT chrome/locale/pt-PT/zotero/
|
||||
locale zotero ro-RO chrome/locale/ro-RO/zotero/
|
||||
locale zotero ru-RU chrome/locale/ru-RU/zotero/
|
||||
locale zotero sk-SK chrome/locale/sk-SK/zotero/
|
||||
locale zotero sl-SI chrome/locale/sl-SI/zotero/
|
||||
locale zotero sr-RS chrome/locale/sr-RS/zotero/
|
||||
locale zotero sv-SE chrome/locale/sv-SE/zotero/
|
||||
locale zotero th-TH chrome/locale/th-TH/zotero/
|
||||
locale zotero tr-TR chrome/locale/tr-TR/zotero/
|
||||
locale zotero uk-UA chrome/locale/uk-UA/zotero/
|
||||
locale zotero vi-VN chrome/locale/vi-VN/zotero/
|
||||
locale zotero zh-CN chrome/locale/zh-CN/zotero/
|
||||
locale zotero zh-TW chrome/locale/zh-TW/zotero/
|
||||
|
||||
skin zotero default chrome/skin/default/zotero/
|
||||
|
||||
overlay chrome://browser/content/browser.xul chrome://zotero/content/overlay.xul
|
||||
|
||||
overlay chrome://zotero/content/preferences/preferences.xul chrome://zotero/content/preferences/preferences_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
overlay chrome://zotero/content/preferences/preferences.xul#cite chrome://zotero/content/preferences/preferences_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
overlay chrome://zotero/content/preferences/preferences_general.xul chrome://zotero/content/preferences/preferences_general_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
overlay chrome://zotero/content/preferences/preferences_export.xul chrome://zotero/content/preferences/preferences_export_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
overlay chrome://zotero/content/preferences/preferences_keys.xul chrome://zotero/content/preferences/preferences_keys_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
overlay chrome://zotero/content/preferences/preferences_advanced.xul chrome://zotero/content/preferences/preferences_advanced_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
overlay chrome://zotero/content/preferences/preferences_advanced.xul chrome://zotero/content/preferences/preferences_advanced_standalone.xul application=zotero@chnm.gmu.edu
|
||||
|
||||
overlay chrome://mozapps/content/downloads/unknownContentType.xul chrome://zotero/content/downloadOverlay.xul
|
||||
|
||||
style chrome://browser/content/browser.xul chrome://zotero/skin/zotero.css
|
||||
style chrome://global/content/customizeToolbar.xul chrome://zotero/skin/zotero.css
|
||||
|
||||
component {e4c61080-ec2d-11da-8ad9-0800200c9a66} components/zotero-service.js
|
||||
component {531828f8-a16c-46be-b9aa-14845c3b010f} components/zotero-service.js
|
||||
contract @zotero.org/Zotero;1 {e4c61080-ec2d-11da-8ad9-0800200c9a66}
|
||||
contract @mozilla.org/commandlinehandler/general-startup;1?type=zotero {531828f8-a16c-46be-b9aa-14845c3b010f}
|
||||
category command-line-handler m-zotero @mozilla.org/commandlinehandler/general-startup;1?type=zotero
|
||||
|
||||
component {06a2ed11-d0a4-4ff0-a56f-a44545eee6ea} components/zotero-autocomplete.js
|
||||
contract @mozilla.org/autocomplete/search;1?name=zotero {06a2ed11-d0a4-4ff0-a56f-a44545eee6ea}
|
||||
|
||||
component {9BC3D762-9038-486A-9D70-C997AF848A7C} components/zotero-protocol-handler.js
|
||||
contract @mozilla.org/network/protocol;1?name=zotero {9BC3D762-9038-486A-9D70-C997AF848A7C}
|
4
chrome/content/zotero-platform/mac/attachmentbox.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
row > label:first-child
|
||||
{
|
||||
color: #7f7f7f;
|
||||
}
|
102
chrome/content/zotero-platform/mac/integration.css
Normal file
|
@ -0,0 +1,102 @@
|
|||
body {
|
||||
line-height: 1.45em;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
body[multiline="true"] {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
#quick-format-dialog {
|
||||
background: transparent;
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
#quick-format-search {
|
||||
background: white;
|
||||
-moz-appearance: searchfield;
|
||||
}
|
||||
|
||||
#quick-format-search[multiline="true"] {
|
||||
padding: 2px 2px 0 19.5px;
|
||||
margin: 2.5px 3.5px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
#quick-format-search:not([multiline="true"]) {
|
||||
padding-top: 4.5px;
|
||||
height: 37px !important;
|
||||
}
|
||||
|
||||
#quick-format-entry {
|
||||
background: -moz-linear-gradient(-90deg, rgb(243,123,119) 0, rgb(180,47,38) 50%, rgb(156,36,27) 50%);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#zotero-icon {
|
||||
margin: -2.5px 0 3px -6px;
|
||||
}
|
||||
|
||||
#quick-format-search[multiline="true"] #zotero-icon {
|
||||
margin: 0 0 1px -13px;
|
||||
}
|
||||
|
||||
#citation-properties menulist {
|
||||
-moz-appearance: none; color: #fff;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.5);
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(0,0,0,.65);
|
||||
background: -moz-linear-gradient(rgba(110,110,110,.9), rgba(70,70,70,.9) 49%, rgba(50,50,50,.9) 51%, rgba(40,40,40,.9));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.2), inset 0 0 1px rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
|
||||
background-clip: padding-box;
|
||||
background-origin: padding-box;
|
||||
padding: 2px 9px;
|
||||
border-radius: 3px;
|
||||
min-height: 22px;
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 0;
|
||||
}
|
||||
|
||||
#citation-properties menulist:-moz-focusring {
|
||||
box-shadow: 0 0 1px -moz-mac-focusring inset, 0 0 4px 1px -moz-mac-focusring, 0 0 2px 1px -moz-mac-focusring;
|
||||
}
|
||||
|
||||
#citation-properties menulist[open="true"],
|
||||
#citation-properties menulist:hover:active {
|
||||
background: -moz-linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9));
|
||||
box-shadow: inset 0 0 3px rgba(0,0,0,.2), inset 0 1px 7px rgba(0,0,0,.4), 0 1px 0 rgba(255,255,255,.1);
|
||||
}
|
||||
|
||||
#citation-properties menulist > .menulist-dropmarker {
|
||||
-moz-appearance: none;
|
||||
display: -moz-box;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#citation-properties menulist > .menulist-dropmarker > .dropmarker-icon {
|
||||
list-style-image: url("chrome://browser/skin/hud-style-dropmarker-double-arrows.png");
|
||||
}
|
||||
|
||||
panel button {
|
||||
-moz-appearance: none; color: #fff; text-shadow: 0 -1px 0 rgba(0,0,0,.5); border-radius: 12px; border: 1px solid rgba(0,0,0,.65); background: -moz-linear-gradient(rgba(110,110,110,.9), rgba(70,70,70,.9) 49%, rgba(50,50,50,.9) 51%, rgba(40,40,40,.9)); box-shadow: inset 0 1px 0 rgba(255,255,255,.2), inset 0 0 1px rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); background-clip: padding-box; background-origin: padding-box; padding: 2px 9px;
|
||||
margin: 6px;
|
||||
min-height: 22px;
|
||||
}
|
||||
|
||||
panel button:hover:active {
|
||||
background: -moz-linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9)); box-shadow: inset 0 0 3px rgba(0,0,0,.2), inset 0 1px 7px rgba(0,0,0,.4), 0 1px 0 rgba(255,255,255,.1);
|
||||
}
|
||||
|
||||
panel button:-moz-focusring {
|
||||
box-shadow: 0 0 1px -moz-mac-focusring inset, 0 0 4px 1px -moz-mac-focusring, 0 0 2px 1px -moz-mac-focusring;
|
||||
}
|
||||
|
||||
.quick-format-bubble {
|
||||
padding: 1px 6px 1px 6px;
|
||||
}
|
32
chrome/content/zotero-platform/mac/itembox.css
Normal file
|
@ -0,0 +1,32 @@
|
|||
scrollbox
|
||||
{
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
row > label:first-child, .creator-type-label, #more-creators-label
|
||||
{
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
.zotero-field-toggle .toolbarbutton-text
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.zotero-field-toggle .toolbarbutton-icon
|
||||
{
|
||||
margin: 0px !important;
|
||||
}
|
||||
|
||||
.creator-type-label > image {
|
||||
margin: 1px .2em 1px;
|
||||
list-style-image: url('chrome://zotero/skin/mac/arrow-down.png');
|
||||
max-width: 7px;
|
||||
max-height: 7px;
|
||||
}
|
||||
|
||||
textbox
|
||||
{
|
||||
margin: -1px 5px -1px 0;
|
||||
padding: 0;
|
||||
}
|
8
chrome/content/zotero-platform/mac/noteeditor.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
row > label:first-child
|
||||
{
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
textbox[type="styled"] {
|
||||
border-style: none;
|
||||
}
|
512
chrome/content/zotero-platform/mac/overlay.css
Normal file
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
As of Fx36, the built-in Mac styles don't properly handle a menu-button within a combined
|
||||
button, so we need this ungodly mess.
|
||||
*/
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"] > separator,
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"]:not(:hover) > .toolbarbutton-menubutton-dropmarker::before,
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:hover > #zotero-toolbar-save-button {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"] {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#zotero-toolbar-main-button[cui-areatype="toolbar"] {
|
||||
margin-right: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
padding-right: 2px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"] {
|
||||
margin-left: -1px;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-left: 0 solid transparent;
|
||||
}
|
||||
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-button {
|
||||
min-width: 27px;
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recreate standard hover effect (except in overflow list)
|
||||
*/
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > #zotero-toolbar-save-button > .toolbarbutton-menubutton-button,
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--toolbarbutton-hover-bordercolor) !important;
|
||||
box-shadow: var(--toolbarbutton-hover-boxshadow) !important;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker::before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > #zotero-toolbar-save-button > .toolbarbutton-menubutton-button {
|
||||
border-right: 1px solid transparent;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker {
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > .toolbarbutton-menubutton-dropmarker {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"]:not([overflowedItem=true]) > .toolbarbutton-menubutton-dropmarker:hover {
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
}
|
||||
|
||||
#zotero-toolbar-main-button[cui-areatype="toolbar"] {
|
||||
border-right: 1px solid transparent;
|
||||
}
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"]:not([overflowedItem=true]):hover {
|
||||
border-left: 0 solid transparent;
|
||||
}
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:not([overflowedItem=true]):hover > #zotero-toolbar-save-button > .toolbarbutton-menubutton-button {
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
|
||||
/* Firefox 55 changes */
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:hover .toolbarbutton-menubutton-button,
|
||||
#zotero-toolbar-buttons[cui-areatype="toolbar"]:hover .toolbarbutton-menubutton-dropmarker,
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"]:hover > .toolbarbutton-menubutton-button,
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"]:hover > .toolbarbutton-menubutton-dropmarker {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Alterations for overflow menu
|
||||
*/
|
||||
#zotero-toolbar-buttons[overflowedItem=true] {
|
||||
margin: 6px 4px 0;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-main-button {
|
||||
max-width: 16px;
|
||||
}
|
||||
|
||||
/* End toolbar icons */
|
||||
|
||||
#zotero-splitter
|
||||
{
|
||||
border-top: none;
|
||||
border-bottom: 1px solid #A3A3A3;
|
||||
min-height: 1px !important;
|
||||
max-height: 1px !important;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#zotero-items-toolbar[state=collapsed]
|
||||
{
|
||||
margin-left: -8px !important;
|
||||
}
|
||||
|
||||
#zotero-pane toolbarseparator {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.5dppx) {
|
||||
#zotero-pane .toolbarbutton-icon {
|
||||
max-width: 28px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-error .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.zotero-tb-button, .zotero-tb-button:first-child, .zotero-tb-button:last-child {
|
||||
-moz-margin-start: 0 !important;
|
||||
-moz-margin-end: 3px !important;
|
||||
-moz-padding-end: 10px !important;
|
||||
background: url("chrome://zotero/skin/mac/menubutton-end.png") right center no-repeat;
|
||||
}
|
||||
|
||||
#zotero-collections-toolbar {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.zotero-tb-button:-moz-window-inactive {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.zotero-tb-button[open="true"],
|
||||
.zotero-tb-button:not([disabled="true"]):hover:active {
|
||||
background: url("chrome://zotero/skin/mac/menubutton-end-pressed.png") right center no-repeat;
|
||||
}
|
||||
|
||||
.zotero-tb-button > menupopup {
|
||||
-moz-margin-start: 2px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.zotero-tb-button > .toolbarbutton-icon {
|
||||
/*-moz-binding: url('chrome://zotero-platform/content/zoterotbbutton.xml#zotero-tb-button');*/
|
||||
background: url("chrome://zotero/skin/mac/menubutton-start.png") left center no-repeat;
|
||||
padding: 5px 1px 5px 11px;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The searchbox focus ring is incorrect in Yosemite pre-Fx34, so use the old searchbox shape
|
||||
* (with code borrowed from the Fx Add-ons window and icons borrowed from the Fx searchbar).
|
||||
* These styles, the 'oldsearchfield' assignment in zoteroPane.js, and the Search.png icons
|
||||
* can be removed after Fx31 ESR.
|
||||
*
|
||||
* Note: This uses navigator.oscpu in zoteroPane.js to test for Yosemite instead of
|
||||
* -moz-mac-yosemite-theme here because the latter isn't defined in Fx31.
|
||||
*/
|
||||
#zotero-pane-stack[oldsearchfield] textbox[type=search] {
|
||||
margin: 0;
|
||||
-moz-appearance: none;
|
||||
padding: 3px 5px 2px;
|
||||
border: 1px solid rgba(60,73,97,0.5);
|
||||
border-radius: 10000px;
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,0.15), 0 1px rgba(255,255,255,0.25);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#zotero-pane-stack[oldsearchfield] textbox[type=search][focused] {
|
||||
box-shadow: 0 0 1px -moz-mac-focusring inset, 0 0 4px 1px -moz-mac-focusring, 0 0 1.5px 1px -moz-mac-focusring, inset 0 1px 1px rgba(0,0,0,0.15);
|
||||
border-color: -moz-mac-focusring;
|
||||
}
|
||||
|
||||
#zotero-pane-stack[oldsearchfield] textbox[type=search] > .textbox-input-box {
|
||||
-moz-padding-start: 15px;
|
||||
background: url("chrome://zotero/skin/mac/moz/Search.png") left no-repeat;
|
||||
background-size: 14px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.5dppx) {
|
||||
#zotero-pane-stack[oldsearchfield] textbox[type=search] > .textbox-input-box {
|
||||
background: url("chrome://zotero/skin/mac/moz/Search@2x.png") left no-repeat;
|
||||
background-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
#zotero-pane-stack[oldsearchfield] textbox[type=search] > .textbox-input-box:-moz-locale-dir(rtl) {
|
||||
background-position: right;
|
||||
}
|
||||
|
||||
#zotero-pane-stack[oldsearchfield] textbox[type=search] > .textbox-input-box > html|*.textbox-input::-moz-placeholder {
|
||||
opacity: 1.0;
|
||||
}
|
||||
/* End searchbox focus fix */
|
||||
|
||||
|
||||
#zotero-tb-search-menu-button
|
||||
{
|
||||
margin: -6px -2px -6px -16px;
|
||||
padding: 6px 2px 6px 14px;
|
||||
list-style-image: url("chrome://zotero/skin/mac/searchbar-dropmarker.png");
|
||||
}
|
||||
|
||||
#zotero-tb-sync > .toolbarbutton-icon {
|
||||
-moz-padding-start: 8px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-error[error=true]
|
||||
{
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.zotero-tb-button[open="true"] > .toolbarbutton-icon,
|
||||
.zotero-tb-button:not([disabled="true"]):hover:active > .toolbarbutton-icon {
|
||||
background: url("chrome://zotero/skin/mac/menubutton-start-pressed.png") left center no-repeat;
|
||||
}
|
||||
|
||||
.zotero-tb-button > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zotero-tb-sync > .toolbarbutton-icon {
|
||||
-moz-binding: none !important;
|
||||
padding: 2px 0px 2px 8px !important;
|
||||
}
|
||||
|
||||
#zotero-close-button {
|
||||
margin: 0px !important;
|
||||
padding: 0px 0px 0px 10px !important;
|
||||
}
|
||||
|
||||
#zotero-tb-sync {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox {
|
||||
background-color: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zotero-item-pane-content .groupbox-body {
|
||||
-moz-appearance: none;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#zotero-item-pane-message {
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox > tabpanels {
|
||||
margin: 12px 0 0 0;
|
||||
padding: 0;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox > tabs {
|
||||
-moz-appearance: none;
|
||||
background: -moz-linear-gradient(top, #ededed, #cccccc);
|
||||
border-style: solid;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: #5e5e5e;
|
||||
padding: 2px 0 2px 0;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox > tabs > tab > hbox {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox > tabs > tab > hbox > .tab-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zotero-pane #zotero-view-tabbox > tabs > tab {
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
-moz-appearance: toolbarbutton;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 3px 1px 3px 1px;
|
||||
}
|
||||
|
||||
#zotero-pane #zotero-view-tabbox > tabs > tab > hbox .tab-text {
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
margin: 2px 7px 2px 9px !important;
|
||||
text-shadow: 0 1px rgba(255, 255, 255, .4);
|
||||
}
|
||||
|
||||
/* This seems to be necessary to center the tabs. Not sure why. */
|
||||
#zotero-pane #zotero-view-tabbox > tabs > tab:last-of-type > hbox .tab-text {
|
||||
margin: 2px 9px 2px 9px !important;
|
||||
}
|
||||
|
||||
#zotero-pane #zotero-view-tabbox > tabs > tab[selected=true] > hbox .tab-text {
|
||||
color: #FFF !important;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0 1px;
|
||||
}
|
||||
|
||||
#zotero-collections-tree {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 5.2em;
|
||||
background-color: #d2d8e2;
|
||||
}
|
||||
|
||||
#zotero-collections-tree:-moz-window-inactive {
|
||||
background-color: rgb(232, 232, 232);
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-row {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-cell(selected) {
|
||||
background: -moz-linear-gradient(top, #A0B0CF, #7386AB) repeat-x;
|
||||
border-top: 1px solid #94A1C0;
|
||||
}
|
||||
|
||||
#zotero-collections-tree:-moz-window-inactive treechildren::-moz-tree-cell(selected) {
|
||||
background: -moz-linear-gradient(top, #B4B4B4, #8A8A8A) repeat-x;
|
||||
border-top: 1px solid #979797;
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-cell(selected, focus) {
|
||||
background: -moz-linear-gradient(top, #6494D4, #2559AC) repeat-x;
|
||||
border-top: 1px solid #5382C5;
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-cell-text(selected) {
|
||||
font-weight: bold !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-twisty(selected) {
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-selected.svg");
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-twisty(selected, open) {
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-selected-open.svg");
|
||||
}
|
||||
|
||||
#zotero-collections-splitter, #zotero-items-splitter
|
||||
{
|
||||
-moz-appearance: none;
|
||||
-moz-border-start: none !important;
|
||||
-moz-border-end: none !important;
|
||||
max-width: 1px !important;
|
||||
min-width: 1px !important;
|
||||
width: 1px !important;
|
||||
background-color: #8b8b8b !important;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed], #zotero-items-splitter[state=collapsed] {
|
||||
border: 0 solid #d6d6d6 !important;
|
||||
max-width: 8px !important;
|
||||
min-width: 8px !important;
|
||||
width: 8px !important;
|
||||
background-image: url("chrome://zotero/skin/mac/vsplitter.png");
|
||||
background-repeat: repeat-y;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed] {
|
||||
border-right-width: 1px !important;
|
||||
}
|
||||
|
||||
#zotero-items-splitter[state=collapsed] {
|
||||
border-left-width: 1px !important;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed] > grippy, #zotero-items-splitter[state=collapsed] > grippy
|
||||
{
|
||||
-moz-appearance: none;
|
||||
background-image: url("chrome://zotero/skin/mac/vgrippy.png");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
#zotero-tags-splitter
|
||||
{
|
||||
-moz-appearance: none;
|
||||
border-top: 1px;
|
||||
border-bottom: 1px;
|
||||
border-color: #A5A5A5;
|
||||
height: 8px;
|
||||
background-image: url("chrome://zotero/skin/mac/hsplitter.png") !important;
|
||||
background-repeat: repeat-x;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zotero-tags-splitter > grippy
|
||||
{
|
||||
-moz-appearance: none;
|
||||
background-image: url("chrome://zotero/skin/mac/hgrippy.png");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
#zotero-tags-splitter > grippy:hover, #zotero-collections-splitter > grippy:hover, #zotero-items-splitter > grippy:hover
|
||||
{
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
#zotero-items-tree
|
||||
{
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zotero-items-tree treechildren::-moz-tree-cell,
|
||||
#zotero-items-tree treechildren::-moz-tree-column {
|
||||
border-right: 1px solid #d7dad7;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-twisty {
|
||||
-moz-appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty.svg");
|
||||
-moz-padding-start: 5px;
|
||||
-moz-padding-end: 6px;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-twisty(open) {
|
||||
-moz-appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-open.svg");
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 7px;
|
||||
}
|
||||
|
||||
/* How to get active twisty?
|
||||
treechildren::-moz-tree-twisty(active) {
|
||||
-moz-appearance: none;
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-active.svg") !important;
|
||||
}
|
||||
|
||||
treechilren::-moz-tree-twisty(active) {
|
||||
-moz-appearance: none;
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-active-open.svg");
|
||||
}
|
||||
*/
|
||||
|
||||
tree:focus treechildren::-moz-tree-twisty(selected) {
|
||||
-moz-appearance: none;
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-selected.svg");
|
||||
}
|
||||
|
||||
tree:focus treechildren::-moz-tree-twisty(selected, open) {
|
||||
-moz-appearance: none;
|
||||
list-style-image: url("chrome://zotero/skin/mac/twisty-selected-open.svg");
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image {
|
||||
height: 16px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
#zotero-tb-advanced-search
|
||||
{
|
||||
list-style-image: url('chrome://zotero/skin/mac/toolbar-advanced-search.png');
|
||||
}
|
||||
|
||||
#zotero-tb-note-add
|
||||
{
|
||||
list-style-image: url('chrome://zotero/skin/mac/toolbar-note-add.png');
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.5dppx) {
|
||||
#zotero-tb-advanced-search {
|
||||
list-style-image: url('chrome://zotero/skin/mac/toolbar-advanced-search@2x.png');
|
||||
}
|
||||
|
||||
#zotero-tb-note-add {
|
||||
list-style-image: url('chrome://zotero/skin/mac/toolbar-note-add@2x.png');
|
||||
}
|
||||
}
|
||||
|
||||
#zotero-tb-actions-menu
|
||||
{
|
||||
list-style-image: url('chrome://zotero/skin/mac/cog.png');
|
||||
}
|
||||
|
||||
#zotero-collectionmenu > .menuitem-iconic, #zotero-itemmenu > .menuitem-iconic, #zotero-collectionmenu > .menu-iconic, #zotero-itemmenu > .menu-iconic {
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 2px !important;
|
||||
list-style-image: none !important;
|
||||
}
|
||||
|
||||
#zotero-collectionmenu > .menuitem-iconic > .menu-iconic-left, #zotero-itemmenu > .menuitem-iconic > .menu-iconic-left, #zotero-collectionmenu > .menu-iconic > .menu-iconic-left, #zotero-itemmenu > .menu-iconic > .menu-iconic-left {
|
||||
display: none;
|
||||
}
|
129
chrome/content/zotero-platform/mac/standalone/menuOverlay.xul
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
The Original Code is Mozilla.org Code.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % standaloneDTD SYSTEM "chrome://zotero/locale/standalone.dtd" >
|
||||
%standaloneDTD;
|
||||
]>
|
||||
<overlay id="menuOverlay"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://global/content/macWindowMenu.js"/>
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
<command id="minimizeWindow"
|
||||
label="&minimizeWindow.label;"
|
||||
oncommand="window.minimize();" />
|
||||
<command id="zoomWindow"
|
||||
label="&zoomWindow.label;"
|
||||
oncommand="zoomWindow();" />
|
||||
</commandset>
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<key id="key_minimizeWindow"
|
||||
command="minimizeWindow"
|
||||
key="&minimizeWindow.key;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_openHelpMac"
|
||||
oncommand="ZoteroStandalone.openHelp();"
|
||||
key="&helpMac.commandkey;"
|
||||
modifiers="accel"/>
|
||||
|
||||
<!-- These are used to build the Application menu under Cocoa widgets -->
|
||||
<key id="key_preferencesCmdMac"
|
||||
key="&preferencesCmdMac.commandkey;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_hideThisAppCmdMac"
|
||||
key="&hideThisAppCmdMac.commandkey;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_hideOtherAppsCmdMac"
|
||||
key="&hideOtherAppsCmdMac.commandkey;"
|
||||
modifiers="accel,alt"/>
|
||||
<key id="key_quitApplication"
|
||||
key="&quitApplicationCmdMac.key;"
|
||||
command="cmd_quitApplication"
|
||||
modifiers="accel"/>
|
||||
</keyset>
|
||||
|
||||
<!-- nsMenuBarX hides these and uses them to build the Application menu. -->
|
||||
<menupopup id="menu_FilePopup">
|
||||
<menuitem id="menu_preferences"
|
||||
label="&preferencesCmdMac.label;"
|
||||
key="key_preferencesCmdMac"
|
||||
oncommand="Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser').ZoteroPane.openPreferences();"/>
|
||||
<menuitem id="menu_mac_services"
|
||||
label="&servicesMenuMac.label;"/>
|
||||
<menuitem id="menu_mac_hide_app"
|
||||
label="&hideThisAppCmdMac.label;"
|
||||
key="key_hideThisAppCmdMac"/>
|
||||
<menuitem id="menu_mac_hide_others"
|
||||
label="&hideOtherAppsCmdMac.label;"
|
||||
key="key_hideOtherAppsCmdMac"/>
|
||||
<menuitem id="menu_mac_show_all"
|
||||
label="&showAllAppsCmdMac.label;"/>
|
||||
<menuitem id="menu_FileQuitItem"
|
||||
label="&quitApplicationCmdMac.label;"
|
||||
key="key_quitApplication"
|
||||
command="cmd_quitApplication"/>
|
||||
</menupopup>
|
||||
|
||||
<menu id="windowMenu"
|
||||
label="&windowMenu.label;"
|
||||
datasources="rdf:window-mediator" ref="NC:WindowMediatorRoot"
|
||||
onpopupshowing="macWindowMenuDidShow();"
|
||||
hidden="false">
|
||||
<template>
|
||||
<rule>
|
||||
<menupopup>
|
||||
<menuitem uri="rdf:*"
|
||||
label="rdf:http://home.netscape.com/NC-rdf#Name"
|
||||
type="radio"
|
||||
name="windowList"
|
||||
oncommand="ShowWindowFromResource(event.target)"/>
|
||||
</menupopup>
|
||||
</rule>
|
||||
</template>
|
||||
<menupopup id="menu_windowPopup">
|
||||
<menuitem command="minimizeWindow" label="&minimizeWindow.label;" key="key_minimizeWindow"/>
|
||||
<menuitem command="zoomWindow" label="&zoomWindow.label;"/>
|
||||
<!-- decomment when "BringAllToFront" is implemented
|
||||
<menuseparator/>
|
||||
<menuitem label="&bringAllToFront.label;" disabled="true"/> -->
|
||||
<menuseparator id="sep-window-list"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</overlay>
|
4
chrome/content/zotero-platform/mac/tab.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
#zotero-toolbar {
|
||||
-moz-appearance: none !important;
|
||||
background: url("chrome://zotero/skin/mac/toolbar-background.png") left center repeat-x;
|
||||
}
|
30
chrome/content/zotero-platform/mac/tagselector.css
Normal file
|
@ -0,0 +1,30 @@
|
|||
groupbox
|
||||
{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
groupbox > .groupbox-body
|
||||
{
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#view-settings-menu .toolbarbutton-menu-dropmarker
|
||||
{
|
||||
margin-left: -12px !important;
|
||||
}
|
||||
|
||||
#no-tags-box
|
||||
{
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
#tag-controls
|
||||
{
|
||||
background-color: rgb(240,240,240);
|
||||
border-width: 1px 0 0 0;
|
||||
border-style: solid;
|
||||
border-color: rgb(220,220,220);
|
||||
padding: 2px 2px 2px 5px;
|
||||
}
|
BIN
chrome/content/zotero-platform/mac/treesource-collection.png
Normal file
After Width: | Height: | Size: 320 B |
BIN
chrome/content/zotero-platform/mac/treesource-search.png
Normal file
After Width: | Height: | Size: 549 B |
BIN
chrome/content/zotero-platform/mac/zotero-z-16px-australis.png
Normal file
After Width: | Height: | Size: 712 B |
BIN
chrome/content/zotero-platform/mac/zotero-z-32px-australis.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
0
chrome/content/zotero-platform/unix/attachmentbox.css
Normal file
24
chrome/content/zotero-platform/unix/integration.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
body {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
#quick-format-search:not([multiline="true"]) {
|
||||
height: 29px !important;
|
||||
}
|
||||
|
||||
#quick-format-search {
|
||||
background: white;
|
||||
padding: 0 2px 0 0;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
#quick-format-dialog {
|
||||
-moz-appearance: none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#zotero-icon {
|
||||
margin: 0 0 0 2px;
|
||||
-moz-appearance: none;
|
||||
}
|
5
chrome/content/zotero-platform/unix/itembox.css
Normal file
|
@ -0,0 +1,5 @@
|
|||
textbox
|
||||
{
|
||||
padding: 1px 2px 1px 1px;
|
||||
margin: -1px 0 -1px 0;
|
||||
}
|
0
chrome/content/zotero-platform/unix/noteeditor.css
Normal file
198
chrome/content/zotero-platform/unix/overlay.css
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
As of Fx36, the built-in styles don't properly handle a menu-button within combined buttons.
|
||||
|
||||
On Windows and Linux, the padding and hover effect (border and shading) are applied directly to
|
||||
the .toolbarbutton-icon (image) instead of the toolbarbutton, so proper sizing of the SVG depends
|
||||
on the total width including border and padding.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Nav bar
|
||||
*/
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-main-button .toolbarbutton-icon {
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button .toolbarbutton-icon {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons #zotero-toolbar-main-button {
|
||||
margin-right: -1px;
|
||||
padding: 0; /* avoid shift on :active */
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-main-button .toolbarbutton-icon {
|
||||
margin-left: 2px;
|
||||
padding-left: 5px !important;
|
||||
padding-right: 5px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button > .toolbarbutton-menubutton-button {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button > .toolbarbutton-menubutton-button .toolbarbutton-icon {
|
||||
padding-left: 6px !important;
|
||||
padding-right: 6px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker {
|
||||
width: 18px !important;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker .dropmarker-icon {
|
||||
padding-left: 14px !important;
|
||||
padding-right: 3px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
padding-left: 8px !important;
|
||||
padding-right: 8px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button:hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button[open] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > separator {
|
||||
/* Copied from .toolbarbutton-menubutton-dropmarker::before */
|
||||
display: -moz-box;
|
||||
width: 1px;
|
||||
height: 18px;
|
||||
-moz-margin-end: -1px;
|
||||
background-clip: padding-box;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1px 18px;
|
||||
box-shadow: var(--toolbarbutton-combined-boxshadow);
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-main-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button .dropmarker-icon {
|
||||
border-color: var(--toolbarbutton-hover-bordercolor) !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button:hover:not(:active) > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button:hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button > .toolbarbutton-menubutton-button:hover:not(:active) > .toolbarbutton-icon,
|
||||
/* This selector doesn't work, so the dropmarker doesn't get a hover effect. :hover doesn't seem
|
||||
to have an effect on either part of the dropmarker */
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker:hover > .dropmarker-icon {
|
||||
background: var(--toolbarbutton-hover-background) !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button:hover:active:not([open]):not([disabled]) .toolbarbutton-menubutton-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button:hover[open]:not([disabled]) .toolbarbutton-menubutton-dropmarker .dropmarker-icon {
|
||||
background: var(--toolbarbutton-active-background);
|
||||
border-color: var(--toolbarbutton-active-bordercolor);
|
||||
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||
transition-duration: 10ms;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Alterations for non-nav-bar toolbars
|
||||
*/
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-main-button > .toolbarbutton-icon,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-main-button-single > .toolbarbutton-icon,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-dropmarker {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-buttons separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Alterations for overflow panel */
|
||||
#zotero-toolbar-main-button-single[overflowedItem=true] .toolbarbutton-icon,
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-main-button .toolbarbutton-icon,
|
||||
#zotero-toolbar-save-button-single[overflowedItem=true] .toolbarbutton-icon,
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-save-button .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] {
|
||||
margin-left: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-main-button {
|
||||
max-width: 28px !important;
|
||||
margin: 0 4px 0 0 !important;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-save-button .toolbarbutton-menubutton-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
/* End toolbar buttons */
|
||||
|
||||
|
||||
/*
|
||||
Override selected, unfocused tree row highlight color, which is too similar to the alternating
|
||||
row color by default
|
||||
*/
|
||||
#zotero-collections-tree treechildren::-moz-tree-row(selected),
|
||||
#zotero-items-tree treechildren::-moz-tree-row(selected) {
|
||||
background-color: #D4D4D4;
|
||||
}
|
||||
|
||||
#zotero-collections-tree treechildren::-moz-tree-row(selected, focus),
|
||||
#zotero-items-tree treechildren::-moz-tree-row(selected, focus) {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
|
||||
@media (min-resolution: 1.5dppx) {
|
||||
#zotero-pane .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync > .toolbarbutton-icon {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.zotero-tb-button:not([type=menu]) {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button {
|
||||
-moz-appearance: toolbarbutton-dropdown !important;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button .button-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zotero-tb-search .textbox-search-icon {
|
||||
visibility: hidden;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
The Original Code is Mozilla.org Code.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % standaloneDTD SYSTEM "chrome://zotero/locale/standalone.dtd" >
|
||||
%standaloneDTD;
|
||||
]>
|
||||
<overlay id="menuOverlay"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<menupopup id="menu_FilePopup">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_FileQuitItem"
|
||||
label="&quitApplicationCmd.label;"
|
||||
key="key_quitApplication"
|
||||
command="cmd_quitApplication"/>
|
||||
</menupopup>
|
||||
<menupopup id="menu_EditPopup">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_preferences"
|
||||
label="&preferencesCmd.label;"
|
||||
oncommand="ZoteroPane.openPreferences();"/>
|
||||
</menupopup>
|
||||
</overlay>
|
0
chrome/content/zotero-platform/unix/tagselector.css
Normal file
BIN
chrome/content/zotero-platform/unix/zotero-z-16px-australis.png
Normal file
After Width: | Height: | Size: 761 B |
BIN
chrome/content/zotero-platform/unix/zotero-z-32px-australis.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
0
chrome/content/zotero-platform/win/attachmentbox.css
Normal file
45
chrome/content/zotero-platform/win/integration.css
Normal file
|
@ -0,0 +1,45 @@
|
|||
#quick-format-dialog {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#quick-format-search {
|
||||
background: white;
|
||||
padding: 2px 2px 2px 0;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border-radius: 10px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
#quick-format-dialog {
|
||||
background: transparent;
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#quick-format-search:not([multiline="true"]) {
|
||||
height: 28px !important;
|
||||
}
|
||||
|
||||
#quick-format-entry {
|
||||
background: -moz-linear-gradient(-90deg, rgb(243,123,119) 0, rgb(180,47,38) 50%, rgb(156,36,27) 50%);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#quick-format-entry:not([square="true"]) {
|
||||
-moz-border-radius: 15px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
#zotero-icon {
|
||||
margin: -1px 0 0 4px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1.65em;
|
||||
}
|
||||
|
||||
body[multiline="true"] {
|
||||
padding-bottom: 2px;
|
||||
}
|
29
chrome/content/zotero-platform/win/itembox.css
Normal file
|
@ -0,0 +1,29 @@
|
|||
row > hbox,
|
||||
row > vbox
|
||||
{
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
row vbox[fieldname]
|
||||
{
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.creator-type-label image {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
textbox
|
||||
{
|
||||
padding: 2px 2px 2px 2px;
|
||||
margin: -1px 0 -1px 1px;
|
||||
}
|
||||
|
||||
#item-type-menu
|
||||
{
|
||||
padding: 0 0 0 1px !important;
|
||||
margin: 0 5px 0 1px !important;
|
||||
}
|
0
chrome/content/zotero-platform/win/noteeditor.css
Normal file
308
chrome/content/zotero-platform/win/overlay.css
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
As of Fx36, the built-in styles don't properly handle a menu-button within combined buttons.
|
||||
|
||||
On Windows and Linux, the padding and hover effect (border and shading) are applied directly to
|
||||
the .toolbarbutton-icon (image) instead of the toolbarbutton, so proper sizing of the SVG depends
|
||||
on the total width including border and padding.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Nav bar
|
||||
*/
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-main-button .toolbarbutton-icon {
|
||||
width: 30px; /* 16 + 1 + 1 + 6 + 6 */
|
||||
padding-left: 6px !important;
|
||||
padding-right: 6px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button .toolbarbutton-icon {
|
||||
width: 29px; /* 16 + 6 + 6 + 1 */
|
||||
padding-left: 6px !important;
|
||||
padding-right: 6px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-main-button-single .toolbarbutton-icon {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button-single .toolbarbutton-icon {
|
||||
width: 31px; /* Compensate for border on only one side */
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker .dropmarker-icon {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > separator {
|
||||
margin-top: 11px;
|
||||
margin-bottom: 11px;
|
||||
-moz-margin-start: -1px !important;
|
||||
-moz-margin-end: -3px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > separator,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker::before {
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons > #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker::before {
|
||||
-moz-margin-end: -1px;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > separator,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button:not([disabled]) > .toolbarbutton-menubutton-dropmarker::before {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-main-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button:not([disabled]) .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button:not([disabled]) .dropmarker-icon {
|
||||
border-color: var(--toolbarbutton-hover-bordercolor) !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-main-button:not(:active) .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover:not([disabled]) > #zotero-toolbar-save-button:not(:active) .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover:not([disabled]) > #zotero-toolbar-save-button:not(:active) .dropmarker-icon {
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button .dropmarker-icon {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-main-button .toolbarbutton-icon {
|
||||
border-top-right-radius: 0px !important;
|
||||
border-bottom-right-radius: 0px !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-buttons:hover > #zotero-toolbar-save-button .toolbarbutton-icon {
|
||||
border-top-left-radius: 0px !important;
|
||||
border-bottom-left-radius: 0px !important;
|
||||
}
|
||||
|
||||
/*
|
||||
There are two hover effects: when the toolbaritem is hovered over, and when the button is hovered over.
|
||||
This applies the latter (and may not be right on different versions of Windows).
|
||||
*/
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-main-button:hover:not(:active):not([disabled]) > .toolbarbutton-icon,
|
||||
/*
|
||||
The dropmarker doesn't honor :hover, so instead of showing the hover effect for each segment individually, do the
|
||||
menu-button parts together, which at least looks like a choice.
|
||||
*/
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button:hover .toolbarbutton-menubutton-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] > #zotero-toolbar-save-button:hover:not(:active):not([disabled]) .toolbarbutton-menubutton-dropmarker .dropmarker-icon {
|
||||
background-color: hsla(210,48%,96%,.75) !important;
|
||||
}
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-main-button:hover > .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button:hover:not([disabled]) .toolbarbutton-menubutton-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button:hover:not([disabled]) .toolbarbutton-menubutton-dropmarker .dropmarker-icon {
|
||||
border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4) !important;
|
||||
box-shadow: 0 0 1px hsla(210,54%,20%,.03),
|
||||
0 0 2px hsla(210,54%,20%,.1) !important;
|
||||
}
|
||||
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button:hover:active:not([open]):not([disabled]) .toolbarbutton-menubutton-button .toolbarbutton-icon,
|
||||
toolbar[id="nav-bar"] #zotero-toolbar-save-button:hover[open]:not([disabled]) .toolbarbutton-menubutton-dropmarker .dropmarker-icon {
|
||||
background: var(--toolbarbutton-active-background) !important;
|
||||
border-color: var(--toolbarbutton-active-bordercolor) !important;
|
||||
box-shadow: var(--toolbarbutton-active-boxshadow) !important;
|
||||
transition-duration: 10ms;
|
||||
}
|
||||
|
||||
#zotero-toolbar-save-button[cui-areatype="toolbar"] > menupopup,
|
||||
#zotero-toolbar-save-button-single[cui-areatype="toolbar"] > menupopup {
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Alterations for non-nav-bar toolbars
|
||||
*/
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-main-button > .toolbarbutton-icon,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-main-button-single > .toolbarbutton-icon,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-main-button-single,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-button,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button > .toolbarbutton-menubutton-button {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button > .toolbarbutton-menubutton-dropmarker,
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-save-button-single > .toolbarbutton-menubutton-dropmarker {
|
||||
padding-left: 2px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
toolbar:not([id="nav-bar"]) #zotero-toolbar-buttons separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Alterations for overflow panel
|
||||
*/
|
||||
#zotero-toolbar-main-button-single[overflowedItem=true] .toolbarbutton-icon,
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-main-button .toolbarbutton-icon,
|
||||
#zotero-toolbar-save-button-single[overflowedItem=true] .toolbarbutton-icon,
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-save-button .toolbarbutton-icon {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] {
|
||||
margin: 6px 0 0 0 !important;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-main-button {
|
||||
max-width: 18px;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-save-button toolbarbutton {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
#zotero-toolbar-buttons[overflowedItem=true] #zotero-toolbar-save-button .toolbarbutton-icon {
|
||||
margin-left: 8px;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
/* End toolbar buttons */
|
||||
|
||||
|
||||
@media (min-resolution: 1.5dppx) {
|
||||
#zotero-toolbar .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync > .toolbarbutton-icon {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button {
|
||||
margin: 0 -1px 0 -4px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
/* Mozilla file copied from chrome://browser/skin/mainwindow-dropdown-arrow.png
|
||||
for availability in Standalone */
|
||||
list-style-image: url("chrome://zotero/skin/win/mainwindow-dropdown-arrow.png");
|
||||
-moz-image-region: rect(0, 13px, 11px, 0);
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button .button-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button:hover:active,
|
||||
#zotero-tb-search-menu-button[open="true"] {
|
||||
-moz-image-region: rect(0, 26px, 11px, 13px);
|
||||
}
|
||||
|
||||
#zotero-tb-search .textbox-search-icon {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-error {
|
||||
margin-right: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync {
|
||||
margin-right: 1px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
#zotero-tb-fullscreen {
|
||||
margin-left: 2px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox tab {
|
||||
padding-left: .7em;
|
||||
padding-right: .7em;
|
||||
}
|
||||
|
||||
#zotero-toolbar {
|
||||
-moz-appearance: toolbox !important;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
#zotero-toolbar:-moz-system-metric(windows-compositor) {
|
||||
-moz-appearance: none !important;
|
||||
background-image: -moz-linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
|
||||
background-color: rgb(207, 219, 236) !important;
|
||||
border-width: 0 0 1px 0;
|
||||
border-style: solid;
|
||||
border-color: #818790;
|
||||
}
|
||||
|
||||
#zotero-collections-tree, #zotero-items-tree, #zotero-view-item {
|
||||
-moz-appearance: none;
|
||||
border-style: solid;
|
||||
border-color: #818790;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-moz-border-top-colors: none;
|
||||
-moz-border-bottom-colors: none;
|
||||
-moz-border-right-colors: none;
|
||||
-moz-border-left-colors: none;
|
||||
}
|
||||
|
||||
/* Undo tree row spacing change in Fx25 on Windows */
|
||||
#zotero-collections-tree treechildren::-moz-tree-row,
|
||||
#zotero-items-tree treechildren::-moz-tree-row,
|
||||
#zotero-prefs treechildren::-moz-tree-row {
|
||||
height: 1.6em;
|
||||
}
|
||||
|
||||
#zotero-collections-tree {
|
||||
border-width: 0 1px 1px 0;
|
||||
}
|
||||
|
||||
/* Restore row highlighting on drag over, though I'm not sure how we're losing it to begin with. */
|
||||
#zotero-collections-tree treechildren::-moz-tree-row(dropOn) {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
#zotero-items-tree {
|
||||
border-width: 0 1px;
|
||||
}
|
||||
|
||||
#zotero-view-item {
|
||||
padding: 0 !important;
|
||||
-moz-appearance: none;
|
||||
background-color: -moz-field;
|
||||
border-width: 1px 0 0 1px;
|
||||
}
|
||||
|
||||
#zotero-view-tabbox > tabs {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
#zotero-item-pane-groupbox {
|
||||
-moz-appearance: none !important;
|
||||
border-radius: 0;
|
||||
border-width: 0 0 0 1px;
|
||||
border-color: #818790;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
#zotero-editpane-item-box > scrollbox, #zotero-view-item > tabpanel > vbox,
|
||||
#zotero-editpane-tags > scrollbox, #zotero-editpane-related {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#zotero-editpane-tags > scrollbox {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
#zotero-view-item > tabpanel > vbox {
|
||||
padding-left: 5px;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
The Original Code is Mozilla.org Code.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % standaloneDTD SYSTEM "chrome://zotero/locale/standalone.dtd" >
|
||||
%standaloneDTD;
|
||||
]>
|
||||
<overlay id="menuOverlay"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<menupopup id="menu_FilePopup">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_FileQuitItem"
|
||||
label="&quitApplicationCmdWin.label;"
|
||||
key="key_quitApplication"
|
||||
command="cmd_quitApplication"/>
|
||||
</menupopup>
|
||||
<menupopup id="menu_ToolsPopup">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_preferences"
|
||||
label="&preferencesCmd.label;"
|
||||
oncommand="ZoteroPane.openPreferences();"/>
|
||||
</menupopup>
|
||||
</overlay>
|
0
chrome/content/zotero-platform/win/tagselector.css
Normal file
BIN
chrome/content/zotero-platform/win/zotero-z-16px-australis.png
Normal file
After Width: | Height: | Size: 773 B |
BIN
chrome/content/zotero-platform/win/zotero-z-32px-australis.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
76
chrome/content/zotero/about.xul
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/about.css" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/about.dtd">
|
||||
|
||||
<dialog
|
||||
id="zotero-about"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
orient="vertical"
|
||||
buttons="accept"
|
||||
buttonlabelaccept="&zotero.about.close;"
|
||||
onload="moveToAlertPosition(); sizeToContent(); document.documentElement.getButton('accept').focus();"
|
||||
ondialogaccept="return true;">
|
||||
|
||||
<script src="include.js"/>
|
||||
|
||||
<vbox id="aboutcontent">
|
||||
<label id="name" value="Zotero"/>
|
||||
<hbox>
|
||||
<label class="zotero-text-link" href="http://zotero.org" value="http://zotero.org"/>
|
||||
</hbox>
|
||||
<label id="version" value="&zotero.version; "/>
|
||||
<script>
|
||||
document.getElementById('version').value += Zotero.version;
|
||||
</script>
|
||||
<hbox>
|
||||
<vbox id="column1">
|
||||
<label class="subhead" value="&zotero.createdby;"/>
|
||||
<vbox class="subcontent">
|
||||
<label class="zotero-text-link" href="http://chnm.gmu.edu" value="Center for History and New Media"/>
|
||||
<label value="George Mason University"/>
|
||||
<label value="Fairfax, VA, USA"/>
|
||||
</vbox>
|
||||
<label class="subhead" value="&zotero.director;"/>
|
||||
<vbox class="subcontent">
|
||||
<label value="Sean Takats"/>
|
||||
</vbox>
|
||||
<label class="subhead" value="&zotero.developers;"/>
|
||||
<vbox class="subcontent">
|
||||
<label value="Dan Stillman"/>
|
||||
<label value="Simon Kornblith"/>
|
||||
<label value="Faolan Cheslack-Postava"/>
|
||||
</vbox>
|
||||
<label class="subhead" value="&zotero.thanks;"/>
|
||||
<vbox class="subcontent">
|
||||
<label class="zotero-text-link" href="http://www.mellon.org/" value="Andrew W. Mellon Foundation"/>
|
||||
<label class="zotero-text-link" href="http://www.imls.gov/" value="Institute of Museum and Library Services"/>
|
||||
<label class="zotero-text-link" href="http://www.sloan.org/" value="Alfred P. Sloan Foundation"/>
|
||||
</vbox>
|
||||
<label class="zotero-text-link" href="http://www.zotero.org/support/credits_and_acknowledgments" value="&zotero.moreCreditsAndAcknowledgements;"/>
|
||||
</vbox>
|
||||
<vbox id="column2">
|
||||
<label class="subhead" value="&zotero.citationProcessing;"/>
|
||||
<vbox class="subcontent">
|
||||
<label class="zotero-text-link" href="http://citationstyles.org/" value="Citation Style Language"/>
|
||||
<label class="zotero-text-link" href="http://bitbucket.org/fbennett/citeproc-js/" value="citeproc-js (Frank Bennett)"/>
|
||||
</vbox>
|
||||
<label class="subhead" value="&zotero.about.additionalSoftware;"/>
|
||||
<vbox class="subcontent">
|
||||
<label class="zotero-text-link" href="http://p.yusukekamiyamane.com/" value="Fugue icons (by Yusuke Kamiyamane)"/>
|
||||
<label class="zotero-text-link" href="http://www.davidashen.net/rnv.html" value="RNV (CSL validation)"/>
|
||||
<label class="zotero-text-link" href="http://documentup.com/kriskowal/q/" value="Q (by Kristopher Michael Kowal)"/>
|
||||
<label class="zotero-text-link" href="https://codefisher.org/pastel-svg/" value="Pastel SVG icons (by Michael Buckley)"/>
|
||||
<label class="zotero-text-link" href="http://www.famfamfam.com/lab/icons/silk/" value="Silk icons (by Mark James)"/>
|
||||
<label class="zotero-text-link" href="http://simile.mit.edu/timeline/" value="SIMILE Project (Timeline)"/>
|
||||
<label class="zotero-text-link" href="http://www.w3.org/2005/ajar/tab" value="Tabulator (RDF parser)"/>
|
||||
<label class="zotero-text-link" href="http://tango.freedesktop.org/Tango_Desktop_Project" value="Tango Desktop Project (pref icons)"/>
|
||||
<label class="zotero-text-link" href="http://tinymce.moxiecode.com/" value="TinyMCE (rich-text editing)"/>
|
||||
<label class="zotero-text-link" href="http://www.dbai.tuwien.ac.at/user/pollak/webpagedump/" value="WebPageDump (snapshot code)"/>
|
||||
<label class="zotero-text-link" href="http://www.foolabs.com/xpdf/" value="Xpdf (pdftotext)"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</dialog>
|
183
chrome/content/zotero/advancedSearch.js
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
var ZoteroAdvancedSearch = new function() {
|
||||
this.onLoad = onLoad;
|
||||
this.search = search;
|
||||
this.clear = clear;
|
||||
this.save = save;
|
||||
this.onDblClick = onDblClick;
|
||||
this.onUnload = onUnload;
|
||||
|
||||
this.itemsView = false;
|
||||
|
||||
var _searchBox;
|
||||
var _libraryID;
|
||||
|
||||
function onLoad() {
|
||||
_searchBox = document.getElementById('zotero-search-box');
|
||||
|
||||
// Set font size from pref
|
||||
var sbc = document.getElementById('zotero-search-box-container');
|
||||
Zotero.setFontSize(sbc);
|
||||
|
||||
_searchBox.onLibraryChange = this.onLibraryChange;
|
||||
var io = window.arguments[0];
|
||||
_searchBox.search = io.dataIn.search;
|
||||
}
|
||||
|
||||
|
||||
function search() {
|
||||
_searchBox.updateSearch();
|
||||
_searchBox.active = true;
|
||||
|
||||
// A minimal implementation of Zotero.ItemGroup
|
||||
var itemGroup = {
|
||||
ref: {
|
||||
libraryID: _libraryID
|
||||
},
|
||||
isSearchMode: function() { return true; },
|
||||
getItems: function () {
|
||||
var search = _searchBox.search.clone();
|
||||
search.libraryID = _libraryID;
|
||||
return Zotero.Items.get(search.search());
|
||||
},
|
||||
isLibrary: function () { return false; },
|
||||
isCollection: function () { return false; },
|
||||
isSearch: function () { return true; },
|
||||
isShare: function () { return false; },
|
||||
isTrash: function () { return false; }
|
||||
}
|
||||
|
||||
if (this.itemsView) {
|
||||
this.itemsView.unregister();
|
||||
}
|
||||
|
||||
this.itemsView = new Zotero.ItemTreeView(itemGroup, false);
|
||||
document.getElementById('zotero-items-tree').view = this.itemsView;
|
||||
}
|
||||
|
||||
|
||||
function clear() {
|
||||
if (this.itemsView) {
|
||||
this.itemsView.unregister();
|
||||
}
|
||||
document.getElementById('zotero-items-tree').view = null;
|
||||
|
||||
var s = new Zotero.Search();
|
||||
// Don't clear the selected library
|
||||
s.libraryID = _searchBox.search.libraryID;
|
||||
s.addCondition('title', 'contains', '');
|
||||
_searchBox.search = s;
|
||||
_searchBox.active = false;
|
||||
}
|
||||
|
||||
|
||||
function save() {
|
||||
_searchBox.updateSearch();
|
||||
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var untitled = Zotero.DB.getNextName(
|
||||
_searchBox.search.libraryID,
|
||||
'savedSearches',
|
||||
'savedSearchName',
|
||||
Zotero.getString('pane.collections.untitled')
|
||||
);
|
||||
|
||||
var name = { value: untitled };
|
||||
var result = promptService.prompt(window,
|
||||
Zotero.getString('pane.collections.newSavedSeach'),
|
||||
Zotero.getString('pane.collections.savedSearchName'), name, "", {});
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!name.value)
|
||||
{
|
||||
name.value = untitled;
|
||||
}
|
||||
|
||||
var s = _searchBox.search.clone();
|
||||
s.name = name.value;
|
||||
s.save();
|
||||
|
||||
window.close();
|
||||
}
|
||||
|
||||
|
||||
this.onLibraryChange = function (libraryID) {
|
||||
_libraryID = libraryID;
|
||||
document.getElementById('zotero-search-save').disabled = !Zotero.Libraries.isEditable(libraryID);
|
||||
}
|
||||
|
||||
|
||||
// Adapted from: http://www.xulplanet.com/references/elemref/ref_tree.html#cmnote-9
|
||||
function onDblClick(event, tree)
|
||||
{
|
||||
if (event && tree && event.type == "dblclick")
|
||||
{
|
||||
var row = {}, col = {}, obj = {};
|
||||
tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, obj);
|
||||
// obj.value == cell/text/image
|
||||
// TODO: handle collection double-click
|
||||
if (obj.value && this.itemsView && this.itemsView.selection.currentIndex > -1)
|
||||
{
|
||||
var item = this.itemsView.getSelectedItems()[0];
|
||||
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
|
||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||
|
||||
if (!lastWin) {
|
||||
window.open();
|
||||
var newWindow = wm.getMostRecentWindow("navigator:browser");
|
||||
var b = newWindow.getBrowser();
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastWin.ZoteroOverlay) {
|
||||
lastWin.ZoteroOverlay.toggleDisplay(true);
|
||||
}
|
||||
|
||||
lastWin.ZoteroPane.selectItem(item.getID(), false, true);
|
||||
lastWin.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onUnload() {
|
||||
// Unregister search from Notifier
|
||||
if (this.itemsView) {
|
||||
this.itemsView.unregister();
|
||||
}
|
||||
}
|
||||
}
|
60
chrome/content/zotero/advancedSearch.xul
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/overlay.css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
%zoteroDTD;
|
||||
<!ENTITY % searchboxDTD SYSTEM "chrome://zotero/locale/searchbox.dtd">
|
||||
%searchboxDTD;
|
||||
]>
|
||||
|
||||
<window
|
||||
id="zotero-advanced-search-dialog"
|
||||
title="&zotero.toolbar.advancedSearch;"
|
||||
orient="vertical"
|
||||
persist="screenX screenY width height"
|
||||
onload="ZoteroAdvancedSearch.onLoad()"
|
||||
onunload="ZoteroAdvancedSearch.onUnload()"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
windowtype="zotero:search">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="advancedSearch.js"/>
|
||||
|
||||
<vbox id="zotero-search-box-container" flex="1">
|
||||
<vbox id="zotero-search-box-controls">
|
||||
<zoterosearch id="zotero-search-box" oncommand="if (this.active) { ZoteroAdvancedSearch.search(); }" flex="1"/>
|
||||
|
||||
<hbox id="zotero-search-buttons">
|
||||
<button label="&zotero.search.search;" default="true" oncommand="ZoteroAdvancedSearch.search()"/>
|
||||
<button label="&zotero.search.clear;" oncommand="ZoteroAdvancedSearch.clear()"/>
|
||||
<button id="zotero-search-save" label="&zotero.search.saveSearch;" oncommand="ZoteroAdvancedSearch.save()"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<tree id="zotero-items-tree" flex="1" hidecolumnpicker="true" seltype="multiple"
|
||||
ondblclick="ZoteroAdvancedSearch.onDblClick(event, this)"
|
||||
ondragstart="if (event.target.localName == 'treechildren') { ZoteroAdvancedSearch.itemsView.onDragStart(event); }">
|
||||
<treecols>
|
||||
<treecol
|
||||
id="zotero-items-column-title" primary="true"
|
||||
label="&zotero.items.title_column;"
|
||||
flex="4" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-firstCreator"
|
||||
label="&zotero.items.creator_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
</treecols>
|
||||
<treechildren alternatingbackground="true"/>
|
||||
</tree>
|
||||
</vbox>
|
||||
|
||||
<keyset>
|
||||
<key id="key_close" key="W" modifiers="accel" oncommand="window.close()"/>
|
||||
</keyset>
|
||||
</window>
|
60
chrome/content/zotero/attachLink.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2014 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_AttachLink = new function() {
|
||||
function getAttachFileLabel() {
|
||||
return window.opener.document
|
||||
.getElementById('zotero-tb-attachment-add-file-link')
|
||||
.label;
|
||||
};
|
||||
|
||||
this.submit = function() {
|
||||
var link = document.getElementById('zotero-attach-uri-input').value;
|
||||
var message = document.getElementById('zotero-attach-uri-message');
|
||||
var cleanURI = Zotero.Attachments.cleanAttachmentURI(link, true);
|
||||
|
||||
if (!cleanURI) {
|
||||
message.textContent = Zotero.getString('pane.items.attach.link.uri.unrecognized');
|
||||
window.sizeToContent();
|
||||
document.getElementById('zotero-attach-uri-input').select();
|
||||
return false;
|
||||
}
|
||||
// Don't allow "file:" links, because using "Attach link to file" is the right way
|
||||
else if (cleanURI.toLowerCase().indexOf('file:') == 0) {
|
||||
message.textContent = Zotero.getString('pane.items.attach.link.uri.file',
|
||||
[getAttachFileLabel()]);
|
||||
window.sizeToContent();
|
||||
document.getElementById('zotero-attach-uri-input').select();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
window.arguments[0].out = {
|
||||
link: cleanURI,
|
||||
title: document.getElementById('zotero-attach-uri-title').value
|
||||
};
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
32
chrome/content/zotero/attachLink.xul
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<dialog
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
buttons="accept,cancel"
|
||||
ondialogaccept="return Zotero_AttachLink.submit();"
|
||||
|
||||
id="zotero-attach-uri-dialog"
|
||||
title="&zotero.attachLink.title;"
|
||||
>
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="attachLink.js"/>
|
||||
|
||||
<vbox id="zotero-attach-uri-container">
|
||||
<hbox>
|
||||
<description id="zotero-attach-uri-message" class="zotero-message-error"></description>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<label id="zotero-attach-uri-label-input" value="&zotero.attachLink.label.link;" control="zotero-attach-uri-input"></label>
|
||||
<textbox id="zotero-attach-uri-input" flex="1"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<label id="zotero-attach-uri-label-title" value="&zotero.attachLink.label.title;" control="zotero-attach-uri-title"></label>
|
||||
<textbox id="zotero-attach-uri-title" flex="1" placeholder="&zotero.general.optional;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</dialog>
|
274
chrome/content/zotero/bibliography.js
Normal file
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zotero_File_Interface_Bibliography
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Class to provide options for bibliography
|
||||
// Used by rtfScan.xul, integrationDocPrefs.xul, and bibliography.xul
|
||||
|
||||
var Zotero_File_Interface_Bibliography = new function() {
|
||||
var _io;
|
||||
|
||||
// Only changes when explicitly selected
|
||||
var lastSelectedStyle,
|
||||
lastSelectedLocale;
|
||||
|
||||
/*
|
||||
* Initialize some variables and prepare event listeners for when chrome is done
|
||||
* loading
|
||||
*/
|
||||
this.init = function () {
|
||||
// Set font size from pref
|
||||
// Affects bibliography.xul and integrationDocPrefs.xul
|
||||
var bibContainer = document.getElementById("zotero-bibliography-container");
|
||||
if(bibContainer) {
|
||||
Zotero.setFontSize(document.getElementById("zotero-bibliography-container"));
|
||||
}
|
||||
|
||||
if(window.arguments && window.arguments.length) {
|
||||
_io = window.arguments[0];
|
||||
if(_io.wrappedJSObject) _io = _io.wrappedJSObject;
|
||||
} else {
|
||||
_io = {};
|
||||
}
|
||||
|
||||
var listbox = document.getElementById("style-listbox");
|
||||
|
||||
// if no style is requested, get the last style used
|
||||
if(!_io.style) {
|
||||
_io.style = Zotero.Prefs.get("export.lastStyle");
|
||||
}
|
||||
|
||||
// add styles to list
|
||||
var styles = Zotero.Styles.getVisible();
|
||||
var index = 0;
|
||||
var nStyles = styles.length;
|
||||
var selectIndex = null;
|
||||
for(var i=0; i<nStyles; i++) {
|
||||
var itemNode = document.createElement("listitem");
|
||||
itemNode.setAttribute("value", styles[i].styleID);
|
||||
itemNode.setAttribute("label", styles[i].title);
|
||||
listbox.appendChild(itemNode);
|
||||
|
||||
if(styles[i].styleID == _io.style) {
|
||||
selectIndex = index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
let requestedLocale;
|
||||
if (selectIndex === null) {
|
||||
// Requested style not found in list, pre-select first style
|
||||
selectIndex = 0;
|
||||
} else {
|
||||
requestedLocale = _io.locale;
|
||||
}
|
||||
|
||||
let style = styles[selectIndex];
|
||||
lastSelectedLocale = Zotero.Prefs.get("export.lastLocale");
|
||||
if (requestedLocale && style && !style.locale) {
|
||||
// pre-select supplied locale
|
||||
lastSelectedLocale = requestedLocale;
|
||||
}
|
||||
|
||||
// add locales to list
|
||||
Zotero.Styles.populateLocaleList(document.getElementById("locale-menu"));
|
||||
|
||||
// Has to be async to work properly
|
||||
window.setTimeout(function () {
|
||||
listbox.ensureIndexIsVisible(selectIndex);
|
||||
listbox.selectedIndex = selectIndex;
|
||||
Zotero_File_Interface_Bibliography.styleChanged();
|
||||
}, 0);
|
||||
|
||||
// ONLY FOR bibliography.xul: export options
|
||||
if(document.getElementById("save-as-rtf")) {
|
||||
var settings = Zotero.Prefs.get("export.bibliographySettings");
|
||||
try {
|
||||
settings = JSON.parse(settings);
|
||||
var mode = settings.mode;
|
||||
var method = settings.method;
|
||||
}
|
||||
// If not JSON, assume it's the previous format-as-a-string
|
||||
catch (e) {
|
||||
method = settings;
|
||||
}
|
||||
if (!mode) mode = "bibliography";
|
||||
if (!method) method = "save-as-rtf";
|
||||
|
||||
// restore saved bibliographic settings
|
||||
document.getElementById('output-mode-radio').selectedItem =
|
||||
document.getElementById(mode);
|
||||
document.getElementById('output-method-radio').selectedItem =
|
||||
document.getElementById(method);
|
||||
}
|
||||
|
||||
// ONLY FOR integrationDocPrefs.xul: update status of displayAs, set
|
||||
// bookmarks text
|
||||
if(document.getElementById("displayAs")) {
|
||||
if(_io.useEndnotes && _io.useEndnotes == 1) document.getElementById("displayAs").selectedIndex = 1;
|
||||
}
|
||||
if(document.getElementById("formatUsing")) {
|
||||
if(_io.fieldType == "Bookmark") document.getElementById("formatUsing").selectedIndex = 1;
|
||||
var formatOption = (_io.primaryFieldType == "ReferenceMark" ? "referenceMarks" : "fields");
|
||||
document.getElementById("fields").label =
|
||||
Zotero.getString("integration."+formatOption+".label");
|
||||
document.getElementById("fields-caption").textContent =
|
||||
Zotero.getString("integration."+formatOption+".caption");
|
||||
document.getElementById("fields-file-format-notice").textContent =
|
||||
Zotero.getString("integration."+formatOption+".fileFormatNotice");
|
||||
document.getElementById("bookmarks-file-format-notice").textContent =
|
||||
Zotero.getString("integration.fields.fileFormatNotice");
|
||||
}
|
||||
if(document.getElementById("automaticJournalAbbreviations-checkbox")) {
|
||||
if(_io.automaticJournalAbbreviations === undefined) {
|
||||
_io.automaticJournalAbbreviations = Zotero.Prefs.get("cite.automaticJournalAbbreviations");
|
||||
}
|
||||
if(_io.automaticJournalAbbreviations) {
|
||||
document.getElementById("automaticJournalAbbreviations-checkbox").checked = true;
|
||||
}
|
||||
}
|
||||
if(document.getElementById("storeReferences")) {
|
||||
if(_io.storeReferences || _io.storeReferences === undefined) {
|
||||
document.getElementById("storeReferences").checked = true;
|
||||
if(_io.requireStoreReferences) document.getElementById("storeReferences").disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// set style to false, in case this is cancelled
|
||||
_io.style = false;
|
||||
};
|
||||
|
||||
/*
|
||||
* Called when locale is changed
|
||||
*/
|
||||
this.localeChanged = function (selectedValue) {
|
||||
lastSelectedLocale = selectedValue;
|
||||
};
|
||||
|
||||
/*
|
||||
* Called when style is changed
|
||||
*/
|
||||
this.styleChanged = function () {
|
||||
var selectedItem = document.getElementById("style-listbox").selectedItem;
|
||||
lastSelectedStyle = selectedItem.getAttribute('value');
|
||||
var selectedStyleObj = Zotero.Styles.get(lastSelectedStyle);
|
||||
|
||||
updateLocaleMenu(selectedStyleObj);
|
||||
|
||||
//
|
||||
// For integrationDocPrefs.xul
|
||||
//
|
||||
|
||||
// update status of displayAs box based on style class
|
||||
if(document.getElementById("displayAs-groupbox")) {
|
||||
var isNote = selectedStyleObj.class == "note";
|
||||
document.getElementById("displayAs-groupbox").hidden = !isNote;
|
||||
|
||||
// update status of formatUsing box based on style class
|
||||
if(document.getElementById("formatUsing")) {
|
||||
if(isNote) document.getElementById("formatUsing").selectedIndex = 0;
|
||||
document.getElementById("bookmarks").disabled = isNote;
|
||||
document.getElementById("bookmarks-caption").disabled = isNote;
|
||||
}
|
||||
}
|
||||
|
||||
// update status of displayAs box based on style class
|
||||
if(document.getElementById("automaticJournalAbbreviations-vbox")) {
|
||||
document.getElementById("automaticJournalAbbreviations-vbox").hidden =
|
||||
!selectedStyleObj.usesAbbreviation;
|
||||
}
|
||||
|
||||
//
|
||||
// For bibliography.xul
|
||||
//
|
||||
|
||||
// Change label to "Citation" or "Note" depending on style class
|
||||
if(document.getElementById("citations")) {
|
||||
let label = "";
|
||||
if(Zotero.Styles.get(lastSelectedStyle).class == "note") {
|
||||
label = Zotero.getString('citation.notes');
|
||||
} else {
|
||||
label = Zotero.getString('citation.citations');
|
||||
}
|
||||
document.getElementById("citations").label = label;
|
||||
}
|
||||
|
||||
window.sizeToContent();
|
||||
};
|
||||
|
||||
/*
|
||||
* Update locale menulist when style is changed
|
||||
*/
|
||||
function updateLocaleMenu(selectedStyle) {
|
||||
Zotero.Styles.updateLocaleList(
|
||||
document.getElementById("locale-menu"),
|
||||
selectedStyle,
|
||||
lastSelectedLocale
|
||||
);
|
||||
}
|
||||
|
||||
this.acceptSelection = function () {
|
||||
// collect code
|
||||
_io.style = document.getElementById("style-listbox").value;
|
||||
|
||||
let localeMenu = document.getElementById("locale-menu");
|
||||
_io.locale = localeMenu.disabled ? undefined : localeMenu.value;
|
||||
|
||||
if(document.getElementById("output-method-radio")) {
|
||||
// collect settings
|
||||
_io.mode = document.getElementById("output-mode-radio").selectedItem.id;
|
||||
_io.method = document.getElementById("output-method-radio").selectedItem.id;
|
||||
// save settings
|
||||
Zotero.Prefs.set("export.bibliographySettings",
|
||||
JSON.stringify({ mode: _io.mode, method: _io.method }));
|
||||
}
|
||||
|
||||
// ONLY FOR integrationDocPrefs.xul:
|
||||
if(document.getElementById("displayAs")) {
|
||||
var automaticJournalAbbreviationsEl = document.getElementById("automaticJournalAbbreviations-checkbox");
|
||||
_io.automaticJournalAbbreviations = automaticJournalAbbreviationsEl.checked;
|
||||
if(!automaticJournalAbbreviationsEl.hidden && lastSelectedStyle) {
|
||||
Zotero.Prefs.set("cite.automaticJournalAbbreviations", _io.automaticJournalAbbreviations);
|
||||
}
|
||||
_io.useEndnotes = document.getElementById("displayAs").selectedIndex;
|
||||
_io.fieldType = (document.getElementById("formatUsing").selectedIndex == 0 ? _io.primaryFieldType : _io.secondaryFieldType);
|
||||
_io.storeReferences = document.getElementById("storeReferences").checked;
|
||||
}
|
||||
|
||||
// remember style and locale if user selected these explicitly
|
||||
if(lastSelectedStyle) {
|
||||
Zotero.Prefs.set("export.lastStyle", _io.style);
|
||||
}
|
||||
|
||||
if (lastSelectedLocale) {
|
||||
Zotero.Prefs.set("export.lastLocale", lastSelectedLocale);
|
||||
}
|
||||
};
|
||||
}
|
42
chrome/content/zotero/bibliography.xul
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/bibliography.css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&zotero.bibliography.title;" buttons="cancel,accept"
|
||||
ondialogaccept="Zotero_File_Interface_Bibliography.acceptSelection()"
|
||||
id="zotero-bibliography"
|
||||
onload="Zotero_File_Interface_Bibliography.init()">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="bibliography.js"/>
|
||||
|
||||
<vbox id="zotero-bibliography-container">
|
||||
<groupbox>
|
||||
<caption label="&zotero.bibliography.style.label;"/>
|
||||
<listbox id="style-listbox" onselect="Zotero_File_Interface_Bibliography.styleChanged()"/>
|
||||
</groupbox>
|
||||
<groupbox>
|
||||
<hbox align="center">
|
||||
<caption label="&zotero.bibliography.locale.label;"/>
|
||||
<menulist id="locale-menu" oncommand="Zotero_File_Interface_Bibliography.localeChanged(this.selectedItem.value)"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
<groupbox>
|
||||
<caption label="&zotero.bibliography.outputMode;"/>
|
||||
<radiogroup id="output-mode-radio">
|
||||
<radio id="citations"/>
|
||||
<radio id="bibliography" label="&zotero.bibliography.bibliography;"/>
|
||||
</radiogroup>
|
||||
</groupbox>
|
||||
<groupbox>
|
||||
<caption label="&zotero.bibliography.outputMethod;"/>
|
||||
<radiogroup id="output-method-radio">
|
||||
<radio id="save-as-rtf" label="&zotero.bibliography.saveAsRTF.label;"/>
|
||||
<radio id="save-as-html" label="&zotero.bibliography.saveAsHTML.label;"/>
|
||||
<radio id="copy-to-clipboard" label="&zotero.bibliography.copyToClipboard.label;"/>
|
||||
<radio id="print" label="&zotero.bibliography.print.label;"/>
|
||||
</radiogroup>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</dialog>
|
561
chrome/content/zotero/bindings/attachmentbox.xml
Normal file
|
@ -0,0 +1,561 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
<!-- <!DOCTYPE bindings SYSTEM "chrome://zotero/locale/attachmentbox.dtd"> -->
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="attachment-box">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/attachmentbox.css"/>
|
||||
<stylesheet src="chrome://zotero-platform/content/attachmentbox.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<!--
|
||||
Public properties
|
||||
-->
|
||||
<field name="editable">false</field>
|
||||
<field name="clickableLink">false</field>
|
||||
<field name="displayButton">false</field>
|
||||
<field name="displayNote">false</field>
|
||||
|
||||
<field name="buttonCaption"/>
|
||||
<field name="clickHandler"/>
|
||||
|
||||
<!-- Modes are predefined settings groups for particular tasks -->
|
||||
<field name="_mode">"view"</field>
|
||||
<property name="mode" onget="return this._mode;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
Zotero.debug("Setting mode to '" + val + "'");
|
||||
|
||||
this.editable = false;
|
||||
this.displayURL = false;
|
||||
this.displayFileName = false;
|
||||
this.clickableLink = false;
|
||||
this.displayAccessed = false;
|
||||
this.displayPages = false;
|
||||
this.displayDateModified = false;
|
||||
this.displayIndexed = false;
|
||||
this.displayNote = false;
|
||||
this.displayNoteIfEmpty = false;
|
||||
|
||||
switch (val) {
|
||||
case 'view':
|
||||
this.displayURL = true;
|
||||
this.displayFileName = true;
|
||||
this.clickableLink = true;
|
||||
this.displayAccessed = true;
|
||||
this.displayPages = true;
|
||||
this.displayIndexed = true;
|
||||
this.displayNote = true;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
this.editable = true;
|
||||
this.displayURL = true;
|
||||
this.displayFileName = true;
|
||||
this.clickableLink = true;
|
||||
this.displayAccessed = true;
|
||||
this.displayPages = true;
|
||||
this.displayIndexed = true;
|
||||
this.displayNote = true;
|
||||
this.displayNoteIfEmpty = true;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
case 'merge':
|
||||
this.displayURL = true;
|
||||
this.displayFileName = true;
|
||||
this.displayAccessed = true;
|
||||
this.displayNote = true;
|
||||
this.displayButton = true;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
case 'mergeedit':
|
||||
this.editable = true;
|
||||
this.displayURL = true;
|
||||
this.displayFileName = true;
|
||||
this.displayAccessed = true;
|
||||
this.displayNote = true;
|
||||
// Notes aren't currently editable in mergeedit pane
|
||||
this.displayNoteIfEmpty = false;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in attachmentbox.xml");
|
||||
}
|
||||
|
||||
this._mode = val;
|
||||
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="_item"/>
|
||||
<property name="item"
|
||||
onget="return this._item;"
|
||||
onset="this._item = val; this.refresh();">
|
||||
</property>
|
||||
|
||||
<!-- .ref is an alias for .item -->
|
||||
<property name="ref"
|
||||
onget="return this._item;"
|
||||
onset="this._item = val; this.refresh();">
|
||||
</property>
|
||||
|
||||
|
||||
<!-- Private properties -->
|
||||
|
||||
<method name="refresh">
|
||||
<body>
|
||||
<![CDATA[
|
||||
Zotero.debug('Refreshing attachment box');
|
||||
|
||||
var attachmentBox = document.getAnonymousNodes(this)[0];
|
||||
var title = this._id('title');
|
||||
var fileNameRow = this._id('fileNameRow');
|
||||
var urlField = this._id('url');
|
||||
var accessed = this._id('accessedRow');
|
||||
var pagesRow = this._id('pagesRow');
|
||||
var dateModifiedRow = this._id('dateModifiedRow');
|
||||
var indexStatusRow = this._id('indexStatusRow');
|
||||
var selectButton = this._id('select-button');
|
||||
|
||||
// DEBUG: this is annoying -- we really want to use an abstracted
|
||||
// version of createValueElement() from itemPane.js
|
||||
// (ideally in an XBL binding)
|
||||
|
||||
// Wrap title to multiple lines if necessary
|
||||
while (title.hasChildNodes()) {
|
||||
title.removeChild(title.firstChild);
|
||||
}
|
||||
var val = this.item.getField('title');
|
||||
|
||||
if (typeof val != 'string') {
|
||||
val += "";
|
||||
}
|
||||
|
||||
var firstSpace = val.indexOf(" ");
|
||||
// Crop long uninterrupted text
|
||||
if ((firstSpace == -1 && val.length > 29 ) || firstSpace > 29) {
|
||||
title.setAttribute('crop', 'end');
|
||||
title.setAttribute('value', val);
|
||||
}
|
||||
// Create a <description> element, essentially
|
||||
else {
|
||||
title.removeAttribute('value');
|
||||
title.appendChild(document.createTextNode(val));
|
||||
}
|
||||
|
||||
if (this.editable) {
|
||||
title.className = 'zotero-clicky';
|
||||
|
||||
// For the time being, use a silly little popup
|
||||
title.addEventListener('click', this.editTitle, false);
|
||||
}
|
||||
|
||||
var isImportedURL = this.item.attachmentLinkMode ==
|
||||
Zotero.Attachments.LINK_MODE_IMPORTED_URL;
|
||||
|
||||
// Metadata for URL's
|
||||
if (this.item.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL
|
||||
|| isImportedURL) {
|
||||
|
||||
// URL
|
||||
if (this.displayURL) {
|
||||
var urlSpec = this.item.getField('url');
|
||||
urlField.setAttribute('value', urlSpec);
|
||||
urlField.setAttribute('hidden', false);
|
||||
if (this.clickableLink) {
|
||||
urlField.onclick = function (event) {
|
||||
ZoteroPane_Local.loadURI(this.value, event)
|
||||
};
|
||||
urlField.className = 'zotero-text-link';
|
||||
}
|
||||
else {
|
||||
urlField.className = '';
|
||||
}
|
||||
urlField.hidden = false;
|
||||
}
|
||||
else {
|
||||
urlField.hidden = true;
|
||||
}
|
||||
|
||||
// Access date
|
||||
if (this.displayAccessed) {
|
||||
this._id("accessed-label").value = Zotero.getString('itemFields.accessDate')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
this._id("accessed").value = Zotero.Date.sqlToDate(
|
||||
this.item.getField('accessDate'), true
|
||||
).toLocaleString();
|
||||
accessed.hidden = false;
|
||||
}
|
||||
else {
|
||||
accessed.hidden = true;
|
||||
}
|
||||
}
|
||||
// Metadata for files
|
||||
else {
|
||||
urlField.hidden = true;
|
||||
accessed.hidden = true;
|
||||
}
|
||||
|
||||
if (this.item.attachmentLinkMode
|
||||
!= Zotero.Attachments.LINK_MODE_LINKED_URL
|
||||
&& this.displayFileName) {
|
||||
var fileName = this.item.getFilename();
|
||||
|
||||
if (fileName) {
|
||||
this._id("fileName-label").value = Zotero.getString('pane.item.attachments.filename')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
this._id("fileName").value = fileName;
|
||||
fileNameRow.hidden = false;
|
||||
}
|
||||
else {
|
||||
fileNameRow.hidden = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fileNameRow.hidden = true;
|
||||
}
|
||||
|
||||
// Page count
|
||||
if (this.displayPages) {
|
||||
var pages = Zotero.Fulltext.getPages(this.item.id);
|
||||
var pages = pages ? pages.total : null;
|
||||
if (pages) {
|
||||
this._id("pages-label").value = Zotero.getString('itemFields.pages')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
this._id("pages").value = pages;
|
||||
pagesRow.hidden = false;
|
||||
}
|
||||
else {
|
||||
pagesRow.hidden = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pagesRow.hidden = true;
|
||||
}
|
||||
|
||||
if (this.displayDateModified) {
|
||||
this._id("dateModified-label").value = Zotero.getString('itemFields.dateModified')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
var mtime = this.item.attachmentModificationTime;
|
||||
if (mtime) {
|
||||
this._id("dateModified").value = new Date(mtime).toLocaleString();
|
||||
}
|
||||
// Use the item's mod time as a backup (e.g., when sync
|
||||
// passes in the mod time for the nonexistent remote file)
|
||||
else {
|
||||
this._id("dateModified").value = Zotero.Date.sqlToDate(
|
||||
this.item.getField('dateModified'), true
|
||||
).toLocaleString();
|
||||
}
|
||||
dateModifiedRow.hidden = false;
|
||||
}
|
||||
else {
|
||||
dateModifiedRow.hidden = true;
|
||||
}
|
||||
|
||||
// Full-text index information
|
||||
if (this.displayIndexed) {
|
||||
this.updateItemIndexedState();
|
||||
indexStatusRow.hidden = false;
|
||||
}
|
||||
else {
|
||||
indexStatusRow.hidden = true;
|
||||
}
|
||||
|
||||
// Note editor
|
||||
var noteEditor = this._id('attachment-note-editor');
|
||||
if (this.displayNote) {
|
||||
if (this.displayNoteIfEmpty || this.item.getNote() != '') {
|
||||
Zotero.debug("setting links on top");
|
||||
noteEditor.linksOnTop = true;
|
||||
noteEditor.hidden = false;
|
||||
|
||||
// Don't make note editable (at least for now)
|
||||
if (this.mode == 'merge' || this.mode == 'mergeedit') {
|
||||
noteEditor.mode = 'merge';
|
||||
noteEditor.displayButton = false;
|
||||
}
|
||||
else {
|
||||
noteEditor.mode = this.mode;
|
||||
}
|
||||
noteEditor.parent = null;
|
||||
noteEditor.item = this.item;
|
||||
}
|
||||
}
|
||||
else {
|
||||
noteEditor.hidden = true;
|
||||
}
|
||||
|
||||
|
||||
if (this.displayButton) {
|
||||
selectButton.label = this.buttonCaption;
|
||||
selectButton.hidden = false;
|
||||
selectButton.setAttribute('oncommand',
|
||||
'document.getBindingParent(this).clickHandler(this)');
|
||||
}
|
||||
else {
|
||||
selectButton.hidden = true;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="editTitle">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var item = document.getBindingParent(this).item;
|
||||
var oldTitle = item.getField('title');
|
||||
|
||||
var nsIPS = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var newTitle = { value: oldTitle };
|
||||
var checkState = { value: Zotero.Prefs.get('lastRenameAssociatedFile') };
|
||||
|
||||
while (true) {
|
||||
// Don't show "Rename associated file" option for
|
||||
// linked URLs
|
||||
if (item.attachmentLinkMode ==
|
||||
Zotero.Attachments.LINK_MODE_LINKED_URL) {
|
||||
var result = nsIPS.prompt(
|
||||
window,
|
||||
'',
|
||||
Zotero.getString('pane.item.attachments.rename.title'),
|
||||
newTitle,
|
||||
null,
|
||||
{}
|
||||
);
|
||||
|
||||
// If they hit cancel or left it blank
|
||||
if (!result || !newTitle.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
var result = nsIPS.prompt(
|
||||
window,
|
||||
'',
|
||||
Zotero.getString('pane.item.attachments.rename.title'),
|
||||
newTitle,
|
||||
Zotero.getString('pane.item.attachments.rename.renameAssociatedFile'),
|
||||
checkState
|
||||
);
|
||||
|
||||
// If they hit cancel or left it blank
|
||||
if (!result || !newTitle.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
Zotero.Prefs.set('lastRenameAssociatedFile', checkState.value);
|
||||
|
||||
// Rename associated file
|
||||
if (checkState.value) {
|
||||
var newFilename = newTitle.value.trim();
|
||||
if (newFilename.search(/\.\w{1,10}$/) == -1) {
|
||||
// User did not specify extension. Use current
|
||||
var oldExt = item.getFilename().match(/\.\w{1,10}$/);
|
||||
if (oldExt) newFilename += oldExt[0];
|
||||
}
|
||||
var renamed = item.renameAttachmentFile(newFilename);
|
||||
if (renamed == -1) {
|
||||
var confirmed = nsIPS.confirm(
|
||||
window,
|
||||
'',
|
||||
newFilename + ' exists. Overwrite existing file?'
|
||||
);
|
||||
if (!confirmed) {
|
||||
// If they said not to overwrite existing file,
|
||||
// start again
|
||||
continue;
|
||||
}
|
||||
|
||||
// Force overwrite, but make sure we check that this doesn't fail
|
||||
renamed = item.renameAttachmentFile(newFilename, true);
|
||||
}
|
||||
|
||||
if (renamed == -2) {
|
||||
nsIPS.alert(
|
||||
window,
|
||||
Zotero.getString('general.error'),
|
||||
Zotero.getString('pane.item.attachments.rename.error')
|
||||
);
|
||||
return;
|
||||
}
|
||||
else if (!renamed) {
|
||||
nsIPS.alert(
|
||||
window,
|
||||
Zotero.getString('pane.item.attachments.fileNotFound.title'),
|
||||
Zotero.getString('pane.item.attachments.fileNotFound.text')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (newTitle.value != oldTitle) {
|
||||
item.setField('title', newTitle.value);
|
||||
item.save();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="onViewClick">
|
||||
<parameter name="event"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
ZoteroPane_Local.viewAttachment(this.item.id, event, !this.editable);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="onShowClick">
|
||||
<parameter name="event"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
ZoteroPane_Local.showAttachmentInFilesystem(this.item.id, event.originalTarget, !this.editable);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<!--
|
||||
Update Indexed: (Yes|No|Partial) line
|
||||
-->
|
||||
<method name="updateItemIndexedState">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var indexStatus = this._id('index-status');
|
||||
var reindexButton = this._id('reindex');
|
||||
|
||||
var status = Zotero.Fulltext.getIndexedState(this.item.id);
|
||||
var str = 'fulltext.indexState.';
|
||||
switch (status) {
|
||||
case Zotero.Fulltext.INDEX_STATE_UNAVAILABLE:
|
||||
str += 'unavailable';
|
||||
break;
|
||||
case Zotero.Fulltext.INDEX_STATE_UNINDEXED:
|
||||
str = 'general.no';
|
||||
break;
|
||||
case Zotero.Fulltext.INDEX_STATE_PARTIAL:
|
||||
str += 'partial';
|
||||
break;
|
||||
case Zotero.Fulltext.INDEX_STATE_INDEXED:
|
||||
str = 'general.yes';
|
||||
break;
|
||||
}
|
||||
this._id("index-status-label").value = Zotero.getString('fulltext.indexState.indexed')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
indexStatus.value = Zotero.getString(str);
|
||||
|
||||
// Reindex button tooltip (string stored in zotero.properties)
|
||||
var str = Zotero.getString('pane.items.menu.reindexItem');
|
||||
reindexButton.setAttribute('tooltiptext', str);
|
||||
|
||||
if (this.editable && Zotero.Fulltext.canReindex(this.item.id)) {
|
||||
reindexButton.setAttribute('hidden', false);
|
||||
}
|
||||
else {
|
||||
reindexButton.setAttribute('hidden', true);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id', id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<vbox id="attachment-box" flex="1" orient="vertical"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<label id="title"/>
|
||||
<label id="url" crop="end"
|
||||
ondragstart="var dt = event.dataTransfer; dt.setData('text/x-moz-url', this.value); dt.setData('text/uri-list', this.value); dt.setData('text/plain', this.value);"/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="fileNameRow">
|
||||
<label id="fileName-label"/>
|
||||
<label id="fileName" crop="end"/>
|
||||
</row>
|
||||
<row id="accessedRow">
|
||||
<label id="accessed-label"/>
|
||||
<label id="accessed"/>
|
||||
</row>
|
||||
<row id="pagesRow">
|
||||
<label id="pages-label"/>
|
||||
<label id="pages"/>
|
||||
</row>
|
||||
<row id="dateModifiedRow">
|
||||
<label id="dateModified-label"/>
|
||||
<label id="dateModified"/>
|
||||
</row>
|
||||
<row id="indexStatusRow">
|
||||
<label id="index-status-label"/>
|
||||
<hbox>
|
||||
<label id="index-status"/>
|
||||
<image id="reindex" onclick="this.hidden = true; setTimeout(function () { ZoteroPane_Local.reindexItem(); }, 50)"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<zoteronoteeditor id="attachment-note-editor" notitle="1" flex="1"/>
|
||||
|
||||
<button id="select-button" hidden="true"/>
|
||||
</vbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
140
chrome/content/zotero/bindings/customcolorpicker.xml
Normal file
|
@ -0,0 +1,140 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
An extension of the Mozilla colorpicker that allows for a custom set of colors
|
||||
-->
|
||||
<bindings id="colorpickerBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="custom-colorpicker" extends="chrome://global/content/bindings/colorpicker.xml#colorpicker">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/customcolorpicker.css"/>
|
||||
</resources>
|
||||
|
||||
<content>
|
||||
<vbox anonid="tiles" flex="1" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<hbox>
|
||||
<image class="colorpickertile" color="#000000"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<constructor><![CDATA[
|
||||
this.initialize();
|
||||
|
||||
this._colors = this.getAttribute('colors');
|
||||
if (this._colors) {
|
||||
this._cols = this.getAttribute('cols');
|
||||
}
|
||||
this.redraw();
|
||||
]]></constructor>
|
||||
|
||||
<!-- Defaults from the Mozilla colorpicker -->
|
||||
<field name="_defaultColors">
|
||||
[
|
||||
'L#FFFFFF','L#FFCCCC','L#FFCC99','L#FFFF99','L#FFFFCC','L#99FF99','L#99FFFF','L#CCFFFF','L#CCCCFF','L#FFCCFF',
|
||||
'#CCCCCC','#FF6666','#FF9966','L#FFFF66','L#FFFF33','L#66FF99','L#33FFFF','L#66FFFF','#9999FF','#FF99FF',
|
||||
'#C0C0C0','#FF0000','#FF9900','#FFCC66','L#FFFF00','L#33FF33','#66CCCC','#33CCFF','#6666CC','#CC66CC',
|
||||
'#999999','#CC0000','#FF6600','#FFCC33','#FFCC00','#33CC00','#00CCCC','#3366FF','#6633FF','#CC33CC',
|
||||
'#666666','#990000','#CC6600','#CC9933','#999900','#009900','#339999','#3333FF','#6600CC','#993399',
|
||||
'#333333','#660000','#993300','#996633','#666600','#006600','#336666','#000099','#333399','#663366',
|
||||
'#000000','#330000','#663300','#663333','#333300','#003300','#003333','#000066','#330099','#330033'
|
||||
]
|
||||
</field>
|
||||
<field name="_defaultCols">10</field>
|
||||
|
||||
<property name="colors" onget="return this._colors ? this._colors : []">
|
||||
<setter><![CDATA[
|
||||
if (typeof val == 'string') {
|
||||
val = val ? val.split(',') : null;
|
||||
}
|
||||
this._colors = val;
|
||||
this.redraw();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="cols" onget="return this.getAttribute('cols')">
|
||||
<setter><![CDATA[
|
||||
this.setAttribute('cols', val);
|
||||
this.redraw();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="redraw">
|
||||
<body><![CDATA[
|
||||
//Zotero.debug("Redrawing color picker");
|
||||
|
||||
var tiles = document.getAnonymousNodes(this)[0];
|
||||
|
||||
var cols = this.getAttribute('cols') || this._defaultCols;
|
||||
var colors = this._colors.concat() || this._defaultColors.concat();
|
||||
|
||||
while (tiles.hasChildNodes()) {
|
||||
tiles.removeChild(tiles.firstChild);
|
||||
}
|
||||
|
||||
var rows = Math.ceil(colors.length / cols);
|
||||
|
||||
var tileWidth = this.getAttribute('tileWidth');
|
||||
var tileHeight = this.getAttribute('tileHeight');
|
||||
|
||||
for (let i=0; i<rows; i++) {
|
||||
var hbox = document.createElement('hbox');
|
||||
for (let j=0; j<cols; j++) {
|
||||
let color = colors.shift();
|
||||
if (!color) {
|
||||
break;
|
||||
}
|
||||
let light = color.charAt(0) == 'L';
|
||||
color = light ? color.substr(1) : color;
|
||||
|
||||
let image = document.createElement('image');
|
||||
image.className = 'colorpickertile' + (light ? ' cp-light' : '');
|
||||
image.setAttribute('color', color);
|
||||
|
||||
let dataURI = "data:image/svg+xml,<svg style='background-color: "
|
||||
+ encodeURIComponent(color) + "' xmlns='http://www.w3.org/2000/svg' />";
|
||||
image.setAttribute('src', dataURI);
|
||||
|
||||
if (tileWidth) {
|
||||
image.width = tileWidth;
|
||||
}
|
||||
if (tileHeight) {
|
||||
image.height = tileHeight;
|
||||
}
|
||||
hbox.appendChild(image);
|
||||
}
|
||||
tiles.appendChild(hbox);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<!-- The content of the Mozilla colorpicker-button, but with a customcolorpicker
|
||||
with some extra inherited attributes instead -->
|
||||
<binding id="custom-colorpicker-button" display="xul:menu"
|
||||
extends="chrome://global/content/bindings/colorpicker.xml#colorpicker-button">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/customcolorpicker.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:image class="colorpicker-button-colorbox" anonid="colorbox" flex="1" xbl:inherits="disabled"/>
|
||||
|
||||
<xul:panel class="colorpicker-button-menupopup"
|
||||
anonid="colorpopup" noautofocus="true" level="top"
|
||||
onmousedown="event.stopPropagation()"
|
||||
onpopupshowing="this._colorPicker.onPopupShowing()"
|
||||
onpopuphiding="this._colorPicker.onPopupHiding()"
|
||||
onselect="this._colorPicker.pickerChange()">
|
||||
<xul:customcolorpicker xbl:inherits="palettename,disabled,cols,columns,tileWidth,tileHeight" allowevents="true" anonid="colorpicker"/>
|
||||
</xul:panel>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<property name="colors" onget="return this.mPicker.colors" onset="this.mPicker.colors = val"/>
|
||||
</implementation>
|
||||
</binding>
|
||||
</bindings>
|
182
chrome/content/zotero/bindings/filesyncstatus.xml
Normal file
|
@ -0,0 +1,182 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2012 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl">
|
||||
<binding id="file-sync-status">
|
||||
<implementation>
|
||||
<property name="data"
|
||||
onget="return this._data;"
|
||||
onset="this._data = val; this.refresh();">
|
||||
</property>
|
||||
|
||||
<field name="_libraries">[]</field>
|
||||
|
||||
<method name="refresh">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var rows = this._id('rows');
|
||||
|
||||
// Get libraries with active downloads or uploads
|
||||
var newLibraries = [];
|
||||
for (var libraryID in this._data) {
|
||||
if ((this._data[libraryID].download
|
||||
&& !this._data[libraryID].download.finished)
|
||||
||
|
||||
(this._data[libraryID].upload
|
||||
&& !this._data[libraryID].upload.finished)) {
|
||||
newLibraries.push(parseInt(libraryID));
|
||||
}
|
||||
}
|
||||
|
||||
// If set of libraries is different, clear and recreate
|
||||
var toRemove = Zotero.Utilities.arrayDiff(this._libraries, newLibraries);
|
||||
var toAdd = Zotero.Utilities.arrayDiff(newLibraries, this._libraries);
|
||||
if (toRemove.length || toAdd.length) {
|
||||
while (rows.hasChildNodes()) {
|
||||
rows.removeChild(rows.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
this._libraries = newLibraries;
|
||||
|
||||
// Update
|
||||
if (rows.hasChildNodes()) {
|
||||
for (var libraryID in this._data) {
|
||||
var libraryStatus = this._data[libraryID];
|
||||
|
||||
// Library is finished
|
||||
if (newLibraries.indexOf(parseInt(libraryID)) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var libraryNameRow = this._id('library-name-row-' + libraryID);
|
||||
var downloadsRow = this._id('downloads-row-' + libraryID);
|
||||
var uploadsRow = this._id('uploads-row-' + libraryID);
|
||||
|
||||
downloadsRow.lastChild.setAttribute('value',
|
||||
libraryStatus.download
|
||||
? libraryStatus.download.statusString
|
||||
: Zotero.getString('sync.storage.none'));
|
||||
uploadsRow.lastChild.setAttribute('value',
|
||||
libraryStatus.upload
|
||||
? libraryStatus.upload.statusString
|
||||
: Zotero.getString('sync.storage.none'));
|
||||
}
|
||||
}
|
||||
// Build from scratch
|
||||
else {
|
||||
// Get ordered list of library names
|
||||
var libraryNames = [];
|
||||
for each(var libraryID in newLibraries) {
|
||||
libraryNames.push({
|
||||
libraryID: libraryID,
|
||||
name: Zotero.Libraries.getName(libraryID)
|
||||
});
|
||||
}
|
||||
var collation = Zotero.getLocaleCollation();
|
||||
libraryNames.sort(function (a, b) {
|
||||
if (a.libraryID == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (b.libraryID == 0) {
|
||||
return 1;
|
||||
}
|
||||
return collation.compareString(1, a.name, b.name);
|
||||
});
|
||||
|
||||
for (var i in libraryNames) {
|
||||
var libraryID = libraryNames[i].libraryID;
|
||||
var libraryStatus = this._data[libraryID];
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.id = 'library-name-row-' + libraryID;
|
||||
label.setAttribute('value', libraryNames[i].name);
|
||||
rows.appendChild(label);
|
||||
|
||||
var row = this._createRow('download',
|
||||
libraryStatus.download
|
||||
? libraryStatus.download.statusString
|
||||
: false);
|
||||
row.id = 'downloads-row-' + libraryID;
|
||||
rows.appendChild(row);
|
||||
|
||||
var row = this._createRow('upload',
|
||||
libraryStatus.upload
|
||||
? libraryStatus.upload.statusString
|
||||
: false);
|
||||
row.id = 'uploads-row-' + libraryID;
|
||||
rows.appendChild(row);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_createRow">
|
||||
<parameter name="type"/>
|
||||
<parameter name="value"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var row = document.createElement('row');
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.setAttribute('value', Zotero.getString('sync.storage.' + type + 's'));
|
||||
row.appendChild(label);
|
||||
|
||||
label = document.createElement('label');
|
||||
label.setAttribute('value',
|
||||
value ? value : Zotero.getString('sync.storage.none'));
|
||||
row.appendChild(label);
|
||||
|
||||
return row;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id', id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<grid xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows id="rows"/>
|
||||
</grid>
|
||||
</content>
|
||||
|
||||
</binding>
|
||||
</bindings>
|
242
chrome/content/zotero/bindings/guidancepanel.xml
Normal file
|
@ -0,0 +1,242 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2011 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="guidancepanel">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/guidancepanel.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<property name="panel" onget="return document.getAnonymousNodes(this)[0]"/>
|
||||
|
||||
<!--
|
||||
@param {Object} [options]
|
||||
@param {String} [options.text] - Text to use in place of firstRunGuidance.<about>
|
||||
@param {DOMElement} [options.forEl] - Anchor node
|
||||
@param {Boolean} [options.force] - Show even if already shown, and don't update
|
||||
firstRunGuidanceShown.<about> pref
|
||||
-->
|
||||
<method name="show">
|
||||
<parameter name="options"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
if(!Zotero.Prefs.get("firstRunGuidance")) return;
|
||||
|
||||
options = options || {};
|
||||
let text = options.text;
|
||||
let useLastText = options.useLastText || false;
|
||||
let forEl = options.forEl || document.getElementById(this.getAttribute("for"));
|
||||
let force = options.force || false;
|
||||
|
||||
if (!forEl) return;
|
||||
// Don't show two panels at once
|
||||
if (Zotero.guidanceBeingShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
var about = this.getAttribute("about");
|
||||
var pref = false;
|
||||
if (about) {
|
||||
pref = "firstRunGuidanceShown." + about;
|
||||
let shown = false;
|
||||
try {
|
||||
shown = Zotero.Prefs.get(pref);
|
||||
} catch(e) {};
|
||||
if (shown && !force) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.guidanceBeingShown = true;
|
||||
|
||||
var x = this.getAttribute("x"),
|
||||
y = this.getAttribute("y"),
|
||||
position = this.getAttribute("position");
|
||||
|
||||
if (!useLastText) {
|
||||
if (!text) {
|
||||
text = Zotero.getString("firstRunGuidance." + about);
|
||||
}
|
||||
text = text.split("\n");
|
||||
var descriptionNode = this.id('panel-description');
|
||||
|
||||
while (descriptionNode.hasChildNodes()) {
|
||||
descriptionNode.removeChild(descriptionNode.firstChild);
|
||||
}
|
||||
|
||||
while(text.length) {
|
||||
var textLine = text.shift();
|
||||
descriptionNode.appendChild(document.createTextNode(textLine));
|
||||
if(text.length) descriptionNode.appendChild(document.createElementNS(
|
||||
"http://www.w3.org/1999/xhtml", "br"));
|
||||
}
|
||||
}
|
||||
|
||||
this.setAttribute(
|
||||
"onpopuphidden",
|
||||
"this.hidden = true; "
|
||||
+ "Zotero.guidanceBeingShown = false; "
|
||||
+ (this.getAttribute("onpopuphidden") || "")
|
||||
);
|
||||
|
||||
this._initNavButton('back', options.back);
|
||||
this._initNavButton('forward', options.forward);
|
||||
|
||||
var self = this;
|
||||
var f = function() {
|
||||
if (self.hasAttribute("foregroundonly") && Services.ww.activeWindow != window) return;
|
||||
|
||||
// Hide panel if content page changes
|
||||
if (self.getAttribute('hideonpagechange') == "true") {
|
||||
let popupShownListener = function () {
|
||||
self.removeEventListener("popupshown", popupShownListener);
|
||||
|
||||
let appcontent = document.getElementById('appcontent');
|
||||
let pageHideListener = function (event) {
|
||||
var doc = event.originalTarget;
|
||||
if(!(doc instanceof HTMLDocument)) return;
|
||||
|
||||
var rootDoc = doc.defaultView.top.document;
|
||||
// Don't hide when frames and special URLs are unloaded
|
||||
if (rootDoc != doc || !rootDoc.location.href.startsWith('http')) {
|
||||
return;
|
||||
}
|
||||
appcontent.removeEventListener("pagehide", pageHideListener);
|
||||
self.hide();
|
||||
};
|
||||
appcontent.addEventListener("pagehide", pageHideListener);
|
||||
};
|
||||
self.addEventListener("popupshown", popupShownListener);
|
||||
}
|
||||
|
||||
self.hidden = false;
|
||||
self.panel.openPopup(forEl, position ? position : "after_start",
|
||||
x ? parseInt(x, 10) : 0, y ? parseInt(y, 10) : 0, false, false, null);
|
||||
if (pref) {
|
||||
Zotero.Prefs.set(pref, true);
|
||||
}
|
||||
};
|
||||
|
||||
if(this.hasAttribute("delay") && !force) {
|
||||
window.setTimeout(f, this.getAttribute("delay"));
|
||||
} else {
|
||||
f();
|
||||
}
|
||||
|
||||
if (this.getAttribute("noautohide") == 'true'
|
||||
&& !this.hasAttribute('forward')) {
|
||||
let listener = function () {
|
||||
this.panel.removeEventListener("click", listener);
|
||||
this.panel.hidePopup();
|
||||
}.bind(this);
|
||||
this.panel.addEventListener("click", listener);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="hide">
|
||||
<body>
|
||||
<![CDATA[
|
||||
document.getAnonymousNodes(this)[0].hidePopup();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_initNavButton">
|
||||
<parameter name="dir"/>
|
||||
<parameter name="nextID"/>
|
||||
<body><![CDATA[
|
||||
if (!nextID) {
|
||||
nextID = this.getAttribute(dir);
|
||||
}
|
||||
if (!nextID) {
|
||||
return;
|
||||
}
|
||||
var nextElem = document.getElementById(nextID);
|
||||
button = this.id(dir + '-button');
|
||||
button.hidden = false;
|
||||
var target;
|
||||
// If there's a forward action and no back action, the whole panel triggers
|
||||
// the forward in noautohide mode
|
||||
if (dir == 'forward' && !this.hasAttribute('back')
|
||||
&& this.getAttribute('noautohide') == 'true') {
|
||||
target = this.panel;
|
||||
}
|
||||
else {
|
||||
target = button;
|
||||
}
|
||||
var listener = function (event) {
|
||||
target.removeEventListener("click", listener);
|
||||
this.hide();
|
||||
var data = {
|
||||
force: true
|
||||
};
|
||||
// Point the next panel back to this one
|
||||
data[dir == 'back' ? 'forward' : 'back'] = this.getAttribute('id');
|
||||
// When going backwards, don't regenerate text
|
||||
if (dir == 'back') {
|
||||
data.useLastText = true;
|
||||
}
|
||||
nextElem.show(data);
|
||||
event.stopPropagation();
|
||||
}.bind(this);
|
||||
target.addEventListener("click", listener);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body><![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('anonid', id)[0];
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:panel type="arrow" align="top" xbl:inherits="noautohide">
|
||||
<xul:stack>
|
||||
<xul:hbox align="center">
|
||||
<xul:image src="chrome://zotero/skin/zotero-new-z-48px.png" style="margin-right: 10px; width: 48px; height: 48px;"/>
|
||||
<xul:description anonid="panel-description" flex="1"></xul:description>
|
||||
</xul:hbox>
|
||||
<xul:hbox anonid="close-button-box">
|
||||
<xul:toolbarbutton anonid="close-button" class="close-icon" hidden="true"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox anonid="nav-buttons">
|
||||
<xul:toolbarbutton anonid="back-button" oncommand="hide()" hidden="true"/>
|
||||
<xul:toolbarbutton anonid="forward-button" oncommand="hide()" hidden="true"/>
|
||||
</xul:hbox>
|
||||
</xul:stack>
|
||||
</xul:panel>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
2530
chrome/content/zotero/bindings/itembox.xml
Normal file
492
chrome/content/zotero/bindings/merge.xml
Normal file
|
@ -0,0 +1,492 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="merge-group">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/merge.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._leftpane = this._id('leftpane');
|
||||
this._rightpane = this._id('rightpane');
|
||||
this._mergepane = this._id('mergepane');
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<field name="_type"/>
|
||||
<property name="type" onget="return this._type;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._type = val;
|
||||
var hbox = document.getAnonymousNodes(this)[0];
|
||||
hbox.setAttribute('mergetype', val);
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="left" onget="return this._leftpane.ref;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
// TODO: Make sure object is the correct type
|
||||
|
||||
if (val == 'deleted') {
|
||||
this._leftpane.ref = 'deleted';
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for note or attachment
|
||||
if (val instanceof Zotero.Item) {
|
||||
this.type = this._getTypeFromItem(val);
|
||||
}
|
||||
|
||||
// Clone object so changes in merge pane don't affect it
|
||||
this._leftpane.ref = val.clone(true);
|
||||
this._leftpane.original = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="right" onget="return this._rightpane.ref;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
// TODO: make sure left is set
|
||||
if (!this._leftpane.ref) {
|
||||
throw ("Left object must be set before setting <zoteromergegroup>.right");
|
||||
}
|
||||
|
||||
if (val == 'deleted') {
|
||||
this._rightpane.ref = 'deleted';
|
||||
}
|
||||
else {
|
||||
// TODO: Make sure object is the correct type
|
||||
|
||||
// Check for note or attachment if not already set
|
||||
if (this._leftpane.ref == 'deleted' && val instanceof Zotero.Item) {
|
||||
this.type = this._getTypeFromItem(val);
|
||||
}
|
||||
|
||||
// Clone object so changes in merge pane don't affect it
|
||||
this._rightpane.ref = val.clone(true);
|
||||
this._rightpane.original = val;
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="merge" onget="return this._mergepane.ref">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
// TODO: Make sure object is the correct type
|
||||
this._mergepane.ref = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="leftCaption" onset="this._leftpane.caption.label = val"/>
|
||||
<property name="rightCaption" onset="this._rightpane.caption.label = val"/>
|
||||
<property name="mergeCaption" onset="this._mergepane.caption.label = val"/>
|
||||
|
||||
|
||||
<property name="leftpane" onget="return this._leftpane"/>
|
||||
<property name="rightpane" onget="return this._rightpane"/>
|
||||
<property name="mergepane" onget="return this._mergepane"/>
|
||||
|
||||
<property name="onSelectionChange"/>
|
||||
|
||||
<field name="_leftpane"/>
|
||||
<field name="_rightpane"/>
|
||||
<field name="_mergepane"/>
|
||||
|
||||
<method name="refresh">
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Set merge pane to most recently changed object
|
||||
// If one object was deleted, set merge pane to other
|
||||
// TODO: use delete timestamp
|
||||
|
||||
if (this._leftpane.ref != 'deleted'
|
||||
&& this._rightpane.ref != 'deleted') {
|
||||
|
||||
var dm1 = this._leftpane.ref.getField('dateModified');
|
||||
if (dm1) {
|
||||
dm1 = Zotero.Date.sqlToDate(dm1);
|
||||
}
|
||||
|
||||
var dm2 = this._rightpane.ref.getField('dateModified');
|
||||
if (dm2) {
|
||||
dm2 = Zotero.Date.sqlToDate(dm2);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._leftpane.ref == 'deleted' || dm2 > dm1) {
|
||||
var mergeItem = this._rightpane.original;
|
||||
this._leftpane.removeAttribute("selected");
|
||||
this._rightpane.setAttribute("selected", "true");
|
||||
}
|
||||
else {
|
||||
var mergeItem = this._leftpane.original;
|
||||
this._rightpane.removeAttribute("selected");
|
||||
this._leftpane.setAttribute("selected", "true");
|
||||
}
|
||||
|
||||
this._mergepane.ref = mergeItem;
|
||||
|
||||
/*
|
||||
|
||||
Code to display only the different values -- not used
|
||||
|
||||
var diff = this._leftpane.ref.diff(this._rightpane.ref, true);
|
||||
|
||||
var fields = [];
|
||||
var diffFields = [];
|
||||
for (var field in diff[0].primary) {
|
||||
fields.push(field);
|
||||
if (diff[0].primary[field] != diff[1].primary[field]) {
|
||||
diffFields.push(field);
|
||||
}
|
||||
}
|
||||
for (var field in diff[0].fields) {
|
||||
fields.push(field);
|
||||
if (diff[0].fields[field] != diff[1].fields[field]) {
|
||||
diffFields.push(field);
|
||||
}
|
||||
}
|
||||
|
||||
this._leftpane.objectbox.fieldOrder = fields;
|
||||
this._rightpane.objectbox.fieldOrder = fields;
|
||||
|
||||
// Display merge pane if item types match
|
||||
if (this._leftpane.ref.itemTypeID == this._rightpane.ref.itemTypeID) {
|
||||
this._leftpane.objectbox.visibleFields = fields;
|
||||
this._rightpane.objectbox.visibleFields = fields;
|
||||
|
||||
this._leftpane.objectbox.clickable = false;
|
||||
this._rightpane.objectbox.clickable = false;
|
||||
this._leftpane.objectbox.clickableFields = diffFields;
|
||||
this._rightpane.objectbox.clickableFields = diffFields;
|
||||
|
||||
var mergeItem = new Zotero.Item(this._leftpane.ref.itemTypeID);
|
||||
this._mergepane.ref = mergeItem;
|
||||
this._mergepane.objectbox.visibleFields = fields;
|
||||
}
|
||||
// Otherwise only allow clicking on item types
|
||||
else {
|
||||
this._leftpane.objectbox.clickableFields = ['itemType'];
|
||||
this._rightpane.objectbox.clickableFields = ['itemType'];
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
this._mergepane.objectbox.editable = true;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
No need to refresh if not comparing fields
|
||||
|
||||
this._leftpane.objectbox.refresh();
|
||||
this._rightpane.objectbox.refresh();
|
||||
*/
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_getTypeFromItem">
|
||||
<parameter name="obj"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!(obj instanceof Zotero.Item)) {
|
||||
throw ("obj is not a Zotero.Item in merge.xml");
|
||||
}
|
||||
if (obj.isAttachment()) {
|
||||
return 'attachment';
|
||||
}
|
||||
else if (obj.isNote()) {
|
||||
return 'note';
|
||||
}
|
||||
else {
|
||||
return 'item';
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:hbox id="merge-group" flex="1">
|
||||
<xul:zoteromergepane id="leftpane" flex="1"/>
|
||||
<xul:zoteromergepane id="rightpane" flex="1"/>
|
||||
<xul:zoteromergepane id="mergepane" flex="1"/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="merge-pane">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/merge.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this.parent = document.getBindingParent(this.parentNode);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="type" onget="return this.parent.type" readonly="true"/>
|
||||
<property name="caption" onget="return this._id('caption')" readonly="true"/>
|
||||
<property name="objectbox" onget="return this._id('objectbox')" readonly="true"/>
|
||||
|
||||
<field name="_deleted"/>
|
||||
<property name="deleted">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._deleted = !!val;
|
||||
|
||||
var placeholder = this._id('object-placeholder');
|
||||
if (placeholder) {
|
||||
placeholder.hidden = !!val;
|
||||
}
|
||||
else {
|
||||
this._id('objectbox').hidden = !!true;
|
||||
}
|
||||
var deleteBox = this._id('delete-box');
|
||||
deleteBox.hidden = !val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="ref" onget="return this._deleted ? 'deleted' : this.objectbox.ref;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
if (val == 'deleted') {
|
||||
this.deleted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.deleted = false;
|
||||
|
||||
// Replace XUL placeholder with XUL object box of given type
|
||||
var elementName;
|
||||
switch (this.type) {
|
||||
case 'item':
|
||||
elementName = 'zoteroitembox';
|
||||
break;
|
||||
|
||||
case 'attachment':
|
||||
elementName = 'zoteroattachmentbox';
|
||||
break;
|
||||
|
||||
case 'note':
|
||||
elementName = 'zoteronoteeditor';
|
||||
break;
|
||||
|
||||
case 'storagefile':
|
||||
elementName = 'zoterostoragefilebox';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Object type '" + this.type
|
||||
+ "' not supported in <zoteromergepane>.ref");
|
||||
}
|
||||
|
||||
var objbox = document.createElement(elementName);
|
||||
|
||||
if (this._id('object-placeholder')) {
|
||||
var placeholder = this._id('object-placeholder');
|
||||
placeholder.parentNode.replaceChild(objbox, placeholder);
|
||||
}
|
||||
else {
|
||||
var oldObjBox = this._id('objectbox');
|
||||
oldObjBox.parentNode.replaceChild(objbox, oldObjBox);
|
||||
}
|
||||
|
||||
objbox.setAttribute("id", "objectbox");
|
||||
objbox.setAttribute("flex", "1");
|
||||
|
||||
if (this.getAttribute('id') == 'mergepane') {
|
||||
objbox.mode = 'mergeedit';
|
||||
}
|
||||
else {
|
||||
objbox.mode = 'merge';
|
||||
objbox.clickHandler = this.chooseObj;
|
||||
}
|
||||
|
||||
// Type-specific settings
|
||||
switch (this.type) {
|
||||
case 'attachment':
|
||||
case 'note':
|
||||
case 'storagefile':
|
||||
objbox.buttonCaption = Zotero.getString('sync.conflict.chooseThisVersion');
|
||||
break;
|
||||
}
|
||||
|
||||
objbox.ref = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="original"/> <!-- original object -->
|
||||
<field name="parent"/>
|
||||
|
||||
<method name="chooseObj">
|
||||
<parameter name="obj"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var pane = Zotero.getAncestorByTagName(obj, 'zoteromergepane');
|
||||
var mergegroup = document.getBindingParent(pane);
|
||||
var mergepane = mergegroup.mergepane;
|
||||
|
||||
if (pane.getAttribute('id') == 'leftpane') {
|
||||
var position = 'left';
|
||||
var otherPane = mergegroup.rightpane;
|
||||
}
|
||||
else {
|
||||
var position = 'right';
|
||||
var otherPane = mergegroup.leftpane;
|
||||
}
|
||||
|
||||
pane.removeAttribute("selected");
|
||||
otherPane.removeAttribute("selected");
|
||||
pane.setAttribute("selected", "true");
|
||||
|
||||
if (pane.ref == 'deleted') {
|
||||
mergepane.deleted = true;
|
||||
}
|
||||
else {
|
||||
mergepane.ref = pane.original;
|
||||
}
|
||||
|
||||
if (mergegroup.onSelectionChange) {
|
||||
mergegroup.onSelectionChange();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Unused -->
|
||||
<method name="chooseField">
|
||||
<parameter name="row"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// If used, has to be updated to handle original item
|
||||
|
||||
var fieldName = row.firstChild.getAttribute('fieldname');
|
||||
// TODO: creator/date
|
||||
var value = row.lastChild.firstChild.nodeValue
|
||||
|
||||
var mergegroup = document.getBindingParent(this.parentNode).parent;
|
||||
var mergepane = mergegroup.mergepane;
|
||||
var pane = document.getBindingParent(this.parentNode);
|
||||
|
||||
if (pane.getAttribute('id') == 'leftpane') {
|
||||
var position = 'left';
|
||||
var otherPane = mergegroup.rightpane;
|
||||
}
|
||||
else {
|
||||
var position = 'right';
|
||||
var otherPane = mergegroup.leftpane;
|
||||
}
|
||||
|
||||
// Changing item type
|
||||
if (fieldName == 'itemType') {
|
||||
fieldName = 'itemTypeID';
|
||||
value = row.lastChild.getAttribute('itemTypeID');
|
||||
|
||||
if (!mergepane.ref) {
|
||||
mergepane.ref = new Zotero.Item(value);
|
||||
}
|
||||
else {
|
||||
mergepane.objectbox.changeTypeTo(value, true);
|
||||
}
|
||||
|
||||
pane.objectbox.clickableFields = [];
|
||||
pane.objectbox.clickable = true;
|
||||
var fieldIDs = Zotero.ItemFields.getItemTypeFields(value);
|
||||
var fieldNames = ['itemType'];
|
||||
for each(var field in fieldIDs) {
|
||||
fieldNames.push(Zotero.ItemFields.getName(field));
|
||||
}
|
||||
otherPane.objectbox.clickableFields = fieldNames;
|
||||
otherPane.objectbox.clickable = false;
|
||||
pane.objectbox.refresh();
|
||||
otherPane.objectbox.refresh();
|
||||
}
|
||||
// Changing another field
|
||||
else {
|
||||
mergepane.ref.setField(fieldName, value);
|
||||
}
|
||||
|
||||
mergepane.objectbox.refresh();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!document.getAnonymousNodes(this)[0].getElementsByAttribute('id', id).length) {
|
||||
return false;
|
||||
}
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id', id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:groupbox id="merge-pane" flex="1">
|
||||
<xul:caption id="caption"/>
|
||||
<xul:box id="object-placeholder"/>
|
||||
<xul:hbox id="delete-box" hidden="true" flex="1"
|
||||
onclick="document.getBindingParent(this).chooseObj(this)">
|
||||
<xul:label value="&zotero.merge.deleted;"/>
|
||||
</xul:hbox>
|
||||
</xul:groupbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
541
chrome/content/zotero/bindings/noteeditor.xml
Normal file
|
@ -0,0 +1,541 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="note-editor">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/noteeditor.css"/>
|
||||
<stylesheet src="chrome://zotero-platform/content/noteeditor.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<!--
|
||||
Public properties
|
||||
-->
|
||||
<field name="editable">false</field>
|
||||
<field name="saveOnEdit">false</field>
|
||||
<field name="displayTags">false</field>
|
||||
<field name="displayRelated">false</field>
|
||||
<field name="displayButton">false</field>
|
||||
|
||||
<field name="buttonCaption"/>
|
||||
<field name="parentClickHandler"/>
|
||||
<field name="keyDownHandler"/>
|
||||
<field name="commandHandler"/>
|
||||
<field name="clickHandler"/>
|
||||
|
||||
<!-- Modes are predefined settings groups for particular tasks -->
|
||||
<field name="_mode">"view"</field>
|
||||
<property name="mode" onget="return this._mode;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
// Duplicate default property settings here
|
||||
this.editable = false;
|
||||
this.saveOnEdit = false;
|
||||
this.displayTags = false;
|
||||
this.displayRelated = false;
|
||||
this.displayButton = false;
|
||||
|
||||
switch (val) {
|
||||
case 'view':
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
this.editable = true;
|
||||
this.saveOnEdit = true;
|
||||
this.parentClickHandler = this.selectParent;
|
||||
this.keyDownHandler = this.handleKeyDown;
|
||||
this.commandHandler = this.save;
|
||||
this.displayTags = true;
|
||||
this.displayRelated = true;
|
||||
break;
|
||||
|
||||
case 'merge':
|
||||
this.displayButton = true;
|
||||
break;
|
||||
|
||||
case 'mergeedit':
|
||||
// Not currently implemented
|
||||
// (editing works, but value isn't saved)
|
||||
//this.editable = true;
|
||||
this.keyDownHandler = this.handleKeyDown;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in noteeditor.xml");
|
||||
}
|
||||
|
||||
this._mode = val;
|
||||
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
||||
this._id('links').mode = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="_parent"/>
|
||||
<property name="parent" onget="return this._parent;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._parent = this._id('links').parent = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="_mtime"/>
|
||||
|
||||
<field name="_item"/>
|
||||
<property name="item" onget="return this._item;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._item = val;
|
||||
// TODO: use clientDateModified instead
|
||||
this._mtime = val.getField('dateModified');
|
||||
|
||||
var parent = this.item.getSourceKey();
|
||||
if (parent) {
|
||||
this.parent = Zotero.Items.getByLibraryAndKey(this.item.libraryID, parent);
|
||||
}
|
||||
|
||||
this._id('links').item = this.item;
|
||||
|
||||
this.refresh();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="linksOnTop">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
if(val) {
|
||||
var links = this._id('linksbox');
|
||||
var parent = links.parentNode;
|
||||
var sib = links.nextSibling;
|
||||
while(parent.firstChild !== links) {
|
||||
parent.insertBefore(parent.removeChild(parent.firstChild), sib);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="note"
|
||||
onget="Zotero.debug('Getting note with .note deprecated -- use .item in zoteronoteeditor'); return this._item"
|
||||
onset="Zotero.debug('Setting note with .note deprecated -- use .item in zoteronoteeditor'); this.item = val"/>
|
||||
<property name="ref" onget="return this._item" onset="this.item = val"/>
|
||||
|
||||
<field name="collection"/>
|
||||
|
||||
<property name="noteField" onget="return this._id('noteField')" readonly="true"/>
|
||||
<property name="value" onget="return this._id('noteField').value;" onset="this._id('noteField').value = val;"/>
|
||||
|
||||
<method name="refresh">
|
||||
<body>
|
||||
<![CDATA[
|
||||
Zotero.debug('Refreshing note editor');
|
||||
|
||||
var textbox = this._id('noteField');
|
||||
var textboxReadOnly = this._id('noteFieldReadOnly');
|
||||
var button = this._id('goButton');
|
||||
|
||||
if (this.editable) {
|
||||
textbox.hidden = false;
|
||||
textboxReadOnly.hidden = true;
|
||||
}
|
||||
else {
|
||||
textbox.hidden = true;
|
||||
textboxReadOnly.hidden = false;
|
||||
textbox = textboxReadOnly;
|
||||
}
|
||||
|
||||
//var scrollPos = textbox.inputField.scrollTop;
|
||||
if (this.item) {
|
||||
textbox.value = this.item.getNote();
|
||||
}
|
||||
else {
|
||||
textbox.value = ''
|
||||
}
|
||||
//textbox.inputField.scrollTop = scrollPos;
|
||||
|
||||
this._id('linksbox').hidden = !(this.displayTags && this.displayRelated);
|
||||
|
||||
if (this.keyDownHandler) {
|
||||
textbox.setAttribute('onkeydown',
|
||||
'document.getBindingParent(this).handleKeyDown(event)');
|
||||
}
|
||||
else {
|
||||
textbox.removeAttribute('onkeydown');
|
||||
}
|
||||
|
||||
if (this.commandHandler) {
|
||||
textbox.setAttribute('oncommand',
|
||||
'document.getBindingParent(this).commandHandler()');
|
||||
}
|
||||
else {
|
||||
textbox.removeAttribute('oncommand');
|
||||
}
|
||||
|
||||
if (this.displayButton) {
|
||||
button.label = this.buttonCaption;
|
||||
button.hidden = false;
|
||||
button.setAttribute('oncommand',
|
||||
'document.getBindingParent(this).clickHandler(this)');
|
||||
}
|
||||
else {
|
||||
button.hidden = true;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="save">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._mode == 'view') {
|
||||
Zotero.debug("Not saving read-only note");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update note
|
||||
var noteField = this._id('noteField');
|
||||
if (this.item) {
|
||||
// If note is reselected automatically after save
|
||||
// from external note window, don't overwrite content
|
||||
//
|
||||
// TODO: use clientDateModified instead
|
||||
if (this.item.getField('dateModified') != this._mtime) {
|
||||
Zotero.debug("Note has already been changed", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
this.item.setNote(noteField.value);
|
||||
if (this.saveOnEdit) {
|
||||
this.item.save();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new note
|
||||
var item = new Zotero.Item('note');
|
||||
if (this.parent) {
|
||||
item.libraryID = this.parent.libraryID;
|
||||
}
|
||||
item.setNote(noteField.value);
|
||||
if (this.parent) {
|
||||
item.setSource(this.parent.id);
|
||||
}
|
||||
if (this.saveOnEdit) {
|
||||
var id = item.save();
|
||||
|
||||
if (!this.parent && this.collection) {
|
||||
this.collection.addItem(id);
|
||||
}
|
||||
}
|
||||
|
||||
this.item = Zotero.Items.get(id);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Used to insert a tab manually -->
|
||||
<method name="handleKeyDown">
|
||||
<parameter name="event"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
switch (event.keyCode) {
|
||||
case 9:
|
||||
if (event.ctrlKey || event.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
// On shift-tab, focus the element specified in
|
||||
// the 'previousfocus' attribute
|
||||
if (event.shiftKey) {
|
||||
let id = this.getAttribute('previousfocus');
|
||||
if (id) {
|
||||
setTimeout(function () {
|
||||
document.getElementById(id).focus();
|
||||
}, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert tab manually
|
||||
//
|
||||
// From http://kb.mozillazine.org/Inserting_text_at_cursor
|
||||
try {
|
||||
var command = "cmd_insertText";
|
||||
var controller = document.commandDispatcher.getControllerForCommand(command);
|
||||
if (controller && controller.isCommandEnabled(command)) {
|
||||
controller = controller.QueryInterface(Components.interfaces.nsICommandController);
|
||||
var params = Components.classes["@mozilla.org/embedcomp/command-params;1"]
|
||||
.createInstance(Components.interfaces.nsICommandParams);
|
||||
params.setStringValue("state_data", "\t");
|
||||
controller.doCommandWithParams(command, params);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug("Can't do cmd_insertText!\n" + e, 1);
|
||||
}
|
||||
|
||||
// DEBUG: is there a better way to prevent blur()?
|
||||
setTimeout(function() { event.target.focus(); }, 1);
|
||||
break;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._id('noteField').focus();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="clearUndo">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._id('noteField').clearUndo();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:vbox xbl:inherits="flex">
|
||||
<xul:textbox id="noteField" type="styled" mode="note"
|
||||
timeout="1000" flex="1" hidden="true"/>
|
||||
<xul:textbox id="noteFieldReadOnly" type="styled" mode="note"
|
||||
readonly="true" flex="1" hidden="true"/>
|
||||
<xul:hbox id="linksbox" hidden="true">
|
||||
<xul:linksbox id="links" flex="1" xbl:inherits="notitle"/>
|
||||
</xul:hbox>
|
||||
<xul:button id="goButton" hidden="true"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="links-box">
|
||||
<implementation>
|
||||
<field name="itemRef"/>
|
||||
<property name="item" onget="return this.itemRef;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.itemRef = val;
|
||||
|
||||
this.id('tags').item = this.item;
|
||||
this.updateTagsSummary();
|
||||
this.id('seeAlso').item = this.item;
|
||||
this.updateSeeAlsoSummary();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<property name="mode">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.id('seeAlso').mode = val;
|
||||
this.id('tags').mode = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<field name="_parent"/>
|
||||
<property name="parent" onget="return this._parent;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._parent = val;
|
||||
|
||||
var parentText = this.id('parentText');
|
||||
if (parentText.firstChild) {
|
||||
parentText.removeChild(parentText.firstChild);
|
||||
}
|
||||
|
||||
if (this._parent && this.getAttribute('notitle') != '1') {
|
||||
this.id('parent-row').hidden = undefined;
|
||||
this.id('parentLabel').value = Zotero.getString('pane.item.parentItem');
|
||||
parentText.appendChild(document.createTextNode(this._parent.getDisplayTitle(true)));
|
||||
}
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<method name="tagsClick">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.id('tags').reload();
|
||||
var x = this.boxObject.screenX;
|
||||
var y = this.boxObject.screenY;
|
||||
this.id('tagsPopup').openPopupAtScreen(x, y, false);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="updateTagsSummary">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var v = this.id('tags').summary;
|
||||
|
||||
if (!v || v == "") {
|
||||
v = "[" + Zotero.getString('pane.item.noteEditor.clickHere') + "]";
|
||||
}
|
||||
|
||||
this.id('tagsLabel').value = Zotero.getString('itemFields.tags')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
this.id('tagsClick').value = v;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="seeAlsoClick">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var relatedList = this.item.relatedItemsBidirectional;
|
||||
if (relatedList.length > 0) {
|
||||
var x = this.boxObject.screenX;
|
||||
var y = this.boxObject.screenY;
|
||||
this.id('seeAlsoPopup').openPopupAtScreen(x, y, false);
|
||||
}
|
||||
else {
|
||||
this.id('seeAlso').add();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="updateSeeAlsoSummary">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var v = this.id('seeAlso').summary;
|
||||
|
||||
if (!v || v == "") {
|
||||
v = "[" + Zotero.getString('pane.item.noteEditor.clickHere') + "]";
|
||||
}
|
||||
|
||||
this.id('seeAlsoLabel').value = Zotero.getString('itemFields.related')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
this.id('seeAlsoClick').value = v;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="parentClick">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this.item || !this.item.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (document.getElementById('zotero-pane')) {
|
||||
var zp = ZoteroPane;
|
||||
}
|
||||
else {
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
|
||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||
|
||||
if (!lastWin) {
|
||||
var lastWin = window.open();
|
||||
}
|
||||
|
||||
if (lastWin.ZoteroOverlay && !lastWin.ZoteroPane.isShowing()) {
|
||||
lastWin.ZoteroOverlay.toggleDisplay(true);
|
||||
}
|
||||
|
||||
var zp = lastWin.ZoteroPane;
|
||||
}
|
||||
|
||||
var parentID = this.item.getSource();
|
||||
zp.clearQuicksearch();
|
||||
zp.selectItem(parentID);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
<content>
|
||||
<xul:vbox xbl:inherits="flex">
|
||||
<xul:grid>
|
||||
<xul:columns>
|
||||
<xul:column/>
|
||||
<xul:column flex="1"/>
|
||||
</xul:columns>
|
||||
<xul:rows>
|
||||
<xul:row id="parent-row" hidden="true">
|
||||
<xul:label id="parentLabel"/>
|
||||
<xul:label id="parentText" class="zotero-clicky" crop="end" onclick="document.getBindingParent(this).parentClick();"/>
|
||||
</xul:row>
|
||||
<xul:row>
|
||||
<xul:label id="seeAlsoLabel"/>
|
||||
<xul:label id="seeAlsoClick" class="zotero-clicky" crop="end" onclick="document.getBindingParent(this).seeAlsoClick();"/>
|
||||
</xul:row>
|
||||
<xul:row>
|
||||
<xul:label id="tagsLabel"/>
|
||||
<xul:label id="tagsClick" class="zotero-clicky" crop="end" onclick="document.getBindingParent(this).tagsClick();"/>
|
||||
</xul:row>
|
||||
</xul:rows>
|
||||
</xul:grid>
|
||||
<xul:popupset>
|
||||
<xul:menupopup id="seeAlsoPopup" width="300" onpopupshowing="this.firstChild.reload();">
|
||||
<xul:seealsobox id="seeAlso" flex="1"/>
|
||||
</xul:menupopup>
|
||||
<!-- The onpopup* stuff is an ugly hack to keep track of when the
|
||||
popup is open (and not the descendent autocomplete popup, which also
|
||||
seems to get triggered by these events for reasons that are less than
|
||||
clear) so that we can manually refresh the popup if it's open after
|
||||
autocomplete is used to prevent it from becoming unresponsive
|
||||
|
||||
Note: Code in tagsbox.xml is dependent on the DOM path between the
|
||||
tagsbox and tagsLabel above, so be sure to update fixPopup() if it changes
|
||||
-->
|
||||
<xul:menupopup id="tagsPopup" ignorekeys="true"
|
||||
onpopupshown="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ /* DEBUG: it would be nice to make this work -- if (this.firstChild.count==0){ this.firstChild.newTag(); } */ this.setAttribute('showing', 'true'); }"
|
||||
onpopuphidden="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ this.setAttribute('showing', 'false'); }">
|
||||
<xul:tagsbox id="tags" flex="1" mode="edit"/>
|
||||
</xul:menupopup>
|
||||
</xul:popupset>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
305
chrome/content/zotero/bindings/relatedbox.xml
Normal file
|
@ -0,0 +1,305 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<binding id="seealso-box">
|
||||
<implementation>
|
||||
<!-- Modes are predefined settings groups for particular tasks -->
|
||||
<field name="_mode">"view"</field>
|
||||
<property name="mode" onget="return this._mode;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.clickable = false;
|
||||
this.editable = false;
|
||||
|
||||
switch (val) {
|
||||
case 'view':
|
||||
case 'merge':
|
||||
case 'mergeedit':
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
this.clickable = true;
|
||||
this.editable = true;
|
||||
//this.clickHandler = this.showEditor;
|
||||
//this.blurHandler = this.hideEditor;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in relatedbox.xml");
|
||||
}
|
||||
|
||||
this._mode = val;
|
||||
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="itemRef"/>
|
||||
<property name="item" onget="return this.itemRef;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.itemRef = val;
|
||||
this.reload();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<property name="summary">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var r = "";
|
||||
|
||||
if (this.item) {
|
||||
var related = this.item.relatedItemsBidirectional;
|
||||
if (related) {
|
||||
related = Zotero.Items.get(related);
|
||||
for(var i = 0; i < related.length; i++) {
|
||||
r = r + related[i].getDisplayTitle() + ", ";
|
||||
}
|
||||
r = r.substr(0,r.length-2);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<method name="reload">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var addButton = this.id('addButton');
|
||||
addButton.hidden = !this.editable;
|
||||
|
||||
var rows = this.id('seeAlsoRows');
|
||||
while(rows.hasChildNodes())
|
||||
rows.removeChild(rows.firstChild);
|
||||
|
||||
if (this.item) {
|
||||
var related = this.item.relatedItemsBidirectional;
|
||||
if (related) {
|
||||
related = Zotero.Items.get(related);
|
||||
for (var i = 0; i < related.length; i++) {
|
||||
var icon= document.createElement("image");
|
||||
icon.className = "zotero-box-icon";
|
||||
var type = Zotero.ItemTypes.getName(related[i].itemTypeID);
|
||||
if (type=='attachment')
|
||||
{
|
||||
switch (related[i].getAttachmentLinkMode())
|
||||
{
|
||||
case Zotero.Attachments.LINK_MODE_LINKED_URL:
|
||||
type += '-web-link';
|
||||
break;
|
||||
|
||||
case Zotero.Attachments.LINK_MODE_IMPORTED_URL:
|
||||
type += '-snapshot';
|
||||
break;
|
||||
|
||||
case Zotero.Attachments.LINK_MODE_LINKED_FILE:
|
||||
type += '-link';
|
||||
break;
|
||||
|
||||
case Zotero.Attachments.LINK_MODE_IMPORTED_FILE:
|
||||
type += '-file';
|
||||
break;
|
||||
}
|
||||
}
|
||||
icon.setAttribute('src','chrome://zotero/skin/treeitem-' + type + '.png');
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.className = "zotero-box-label";
|
||||
label.setAttribute('value', related[i].getDisplayTitle());
|
||||
label.setAttribute('crop','end');
|
||||
label.setAttribute('flex','1');
|
||||
|
||||
var box = document.createElement('box');
|
||||
box.setAttribute('onclick',
|
||||
"document.getBindingParent(this).showItem('" + related[i].id + "')");
|
||||
box.setAttribute('class','zotero-clicky');
|
||||
box.setAttribute('flex','1');
|
||||
box.appendChild(icon);
|
||||
box.appendChild(label);
|
||||
|
||||
if (this.editable) {
|
||||
var remove = document.createElement("label");
|
||||
remove.setAttribute('value','-');
|
||||
remove.setAttribute('onclick',
|
||||
"document.getBindingParent(this).remove('" + related[i].id + "');");
|
||||
remove.setAttribute('class','zotero-clicky zotero-clicky-minus');
|
||||
}
|
||||
|
||||
var row = document.createElement("row");
|
||||
row.appendChild(box);
|
||||
if (this.editable) {
|
||||
row.appendChild(remove);
|
||||
}
|
||||
row.setAttribute('id', 'seealso-' + related[i].id);
|
||||
rows.appendChild(row);
|
||||
}
|
||||
this.updateCount(related.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.updateCount();
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="add">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var io = {dataIn: null, dataOut: null};
|
||||
|
||||
window.openDialog('chrome://zotero/content/selectItemsDialog.xul', '',
|
||||
'chrome,dialog=no,modal,centerscreen,resizable=yes', io);
|
||||
|
||||
if(io.dataOut) {
|
||||
if (io.dataOut.length) {
|
||||
var relItem = Zotero.Items.get(io.dataOut[0]);
|
||||
if (relItem.libraryID != this.item.libraryID) {
|
||||
// FIXME
|
||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
ps.alert(null, "", "You cannot relate items in different libraries in this Zotero release.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
for(var i = 0; i < io.dataOut.length; i++) {
|
||||
this.item.addRelatedItem(io.dataOut[i]);
|
||||
}
|
||||
this.item.save();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="remove">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if(id) {
|
||||
// TODO: set attribute on reload to determine
|
||||
// which of these is necessary
|
||||
this.item.removeRelatedItem(id);
|
||||
this.item.save();
|
||||
|
||||
var item = Zotero.Items.get(id);
|
||||
item.removeRelatedItem(this.item.id);
|
||||
item.save();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="showItem">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if(id)
|
||||
{
|
||||
var p;
|
||||
if(window.ZoteroPane_Local)
|
||||
{
|
||||
p = window.ZoteroPane_Local;
|
||||
}
|
||||
else
|
||||
{
|
||||
var win;
|
||||
|
||||
if(window.opener && window.opener.ZoteroPane)
|
||||
{
|
||||
win = window.opener;
|
||||
}
|
||||
else
|
||||
{
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
win = wm.getMostRecentWindow('navigator:browser');
|
||||
if(!win)
|
||||
return;
|
||||
}
|
||||
|
||||
p = win.ZoteroPane;
|
||||
}
|
||||
|
||||
p.selectItem(id);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="updateCount">
|
||||
<parameter name="count"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (count == null) {
|
||||
var count = this.item.relatedItemsBidirectional.length;
|
||||
}
|
||||
|
||||
var str = 'pane.item.related.count.';
|
||||
switch (count){
|
||||
case 0:
|
||||
str += 'zero';
|
||||
break;
|
||||
case 1:
|
||||
str += 'singular';
|
||||
break;
|
||||
default:
|
||||
str += 'plural';
|
||||
break;
|
||||
}
|
||||
this.id('seeAlsoNum').value = Zotero.getString(str, [count]);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
<content>
|
||||
<xul:vbox xbl:inherits="flex" class="zotero-box">
|
||||
<xul:hbox align="center">
|
||||
<xul:label id="seeAlsoNum"/>
|
||||
<xul:button id="addButton" label="&zotero.item.add;"
|
||||
oncommand="this.parentNode.parentNode.parentNode.add();"/>
|
||||
</xul:hbox>
|
||||
<xul:grid flex="1">
|
||||
<xul:columns>
|
||||
<xul:column flex="1"/>
|
||||
<xul:column/>
|
||||
</xul:columns>
|
||||
<xul:rows id="seeAlsoRows"/>
|
||||
</xul:grid>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
54
chrome/content/zotero/bindings/resizabledialog.xml
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<binding id="resizabledialog" extends="chrome://global/content/bindings/dialog.xml#dialog">
|
||||
<content style="padding: 0">
|
||||
<xul:vbox class="box-inherit dialog-content-box" flex="1" style="padding:14px 14px 0 14px">
|
||||
<children/>
|
||||
</xul:vbox>
|
||||
|
||||
<xul:stack>
|
||||
<xul:hbox align="end" pack="end">
|
||||
<xul:resizer dir="bottomright" style="-moz-appearance: resizer"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="dialog-button-box" anonid="buttons"
|
||||
xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
|
||||
flex="1" style="padding: 10px 14px 14px 14px; margin: 0">
|
||||
<xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="help" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
|
||||
<xul:spacer anonid="spacer" flex="1"/>
|
||||
<xul:button dlgtype="cancel" class="dialog-button"/>
|
||||
<xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
|
||||
</xul:hbox>
|
||||
</xul:stack>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
70
chrome/content/zotero/bindings/storagefilebox.xml
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="storage-file-box"
|
||||
extends="chrome://zotero/content/bindings/attachmentbox.xml#attachment-box">
|
||||
|
||||
<implementation>
|
||||
<property name="mode" onget="return this._mode;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.editable = false;
|
||||
this.displayGoButtons = false;
|
||||
this.clickableLink = false;
|
||||
this.displayIndexed = false;
|
||||
this.displayPages = false;
|
||||
this.displayNote = false;
|
||||
|
||||
switch (val) {
|
||||
case 'merge':
|
||||
this.displayFileName = true;
|
||||
this.displayButton = true;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
case 'mergeedit':
|
||||
this.displayFileName = true;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in storagefilebox.xml");
|
||||
}
|
||||
|
||||
this._mode = val;
|
||||
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
</bindings>
|
738
chrome/content/zotero/bindings/styled-textbox.xml
Normal file
|
@ -0,0 +1,738 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<binding id="styled-textbox">
|
||||
<implementation>
|
||||
<field name="_editable"/>
|
||||
<field name="_mode"/>
|
||||
<field name="_format"/>
|
||||
<field name="_loadHandler"/>
|
||||
<field name="_commandString"/>
|
||||
<field name="_eventHandler"/>
|
||||
<field name="_editor"/>
|
||||
<field name="_value"/>
|
||||
<field name="_timer"/>
|
||||
<field name="_focus"/>
|
||||
<field name="_constructed"/>
|
||||
<field name="_loadOnConstruct"/>
|
||||
|
||||
<constructor><![CDATA[
|
||||
this.mode = this.getAttribute('mode');
|
||||
|
||||
this._iframe = document.getAnonymousElementByAttribute(this, "anonid", "rt-view");
|
||||
|
||||
this._htmlRTFmap = [
|
||||
// Atomic units, HTML -> RTF (cleanup)
|
||||
[/<br \/>/g, "\x0B"],
|
||||
[/"(\w)/g, "“$1"],
|
||||
[/([\w,.?!])"/g, "$1”"],
|
||||
[/<p>/g, ""],
|
||||
//[/<\/p>(?!\s*$)/g, "\\par{}"],
|
||||
[/<\/?div[^>]*>/g, ""],
|
||||
[/[\x7F-\uFFFF]/g, function(aChar) { return "\\uc0\\u"+aChar.charCodeAt(0).toString()+"{}"}]
|
||||
];
|
||||
|
||||
this._rtfHTMLmap = [
|
||||
// Atomic units, RTF -> HTML (cleanup)
|
||||
[/\\uc0\{?\\u([0-9]+)\}?(?:{}| )?/g, function(wholeStr, aCode) { return String.fromCharCode(aCode) }],
|
||||
[/\\tab(?:\{\}| )/g, '<span class="tab"> </span>'],
|
||||
[/(?:\\par{}|\\\r?\n)/g, "</p><p>"]
|
||||
];
|
||||
|
||||
this.init = function() {
|
||||
if (this.initialized) return;
|
||||
// Tag data
|
||||
var _rexData = [
|
||||
[
|
||||
[
|
||||
["<span style=\"font-variant:small-caps;\">"],
|
||||
["{\\scaps ", "{\\scaps{}"]
|
||||
],
|
||||
[
|
||||
["<\/span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span style=\"text-decoration:underline;\">"],
|
||||
["{\\ul{}", "{\\ul "]
|
||||
],
|
||||
[
|
||||
["<\/span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<sup>"],
|
||||
["\\super ", "\\super{}"]
|
||||
],
|
||||
[
|
||||
["</sup>"],
|
||||
["\\nosupersub{}", "\\nosupersub "]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<sub>"],
|
||||
["\\sub ", "\\sub{}"]
|
||||
],
|
||||
[
|
||||
["</sub>"],
|
||||
["\\nosupersub{}", "\\nosupersub "]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<em>"],
|
||||
["{\\i{}", "{\\i "]
|
||||
],
|
||||
[
|
||||
["</em>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<i>"],
|
||||
["{\\i{}", "{\\i "]
|
||||
],
|
||||
[
|
||||
["</i>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<b>"],
|
||||
["{\\b{}", "{\\b "]
|
||||
],
|
||||
[
|
||||
["</b>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<strong>"],
|
||||
["{\\b{}", "{\\b "]
|
||||
],
|
||||
[
|
||||
["</strong>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span style=\"font-variant:normal;\">"],
|
||||
["{\\scaps0{}", "{\\scaps0 "]
|
||||
],
|
||||
[
|
||||
["</span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span style=\"font-style:normal;\">"],
|
||||
["{\\i0{}", "{\\i0 "]
|
||||
],
|
||||
[
|
||||
["</span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span style=\"font-weight:normal;\">"],
|
||||
["{\\b0{}", "{\\b0 "]
|
||||
],
|
||||
[
|
||||
["</span>"],
|
||||
["}"]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
function longestFirst(a, b) {
|
||||
if (a.length < b.length) {
|
||||
return 1;
|
||||
} else if (a.length > b.length) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function composeRex(rexes, noGlobal) {
|
||||
var lst = [];
|
||||
for (var rex in rexes) {
|
||||
lst.push(rex);
|
||||
}
|
||||
lst.sort(longestFirst);
|
||||
var rexStr = "(?:" + lst.join("|") + ")";
|
||||
return new RegExp(rexStr, "g");
|
||||
}
|
||||
|
||||
// Create splitting regexps
|
||||
function splitRexMaker(segment) {
|
||||
var rexes = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
for (var j=0,jlen=_rexData[i].length; j < jlen; j++) {
|
||||
for (var k=0,klen=_rexData[i][j][segment].length; k < klen; k++) {
|
||||
rexes[_rexData[i][j][segment][k].replace("\\", "\\\\")] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
var ret = composeRex(rexes, true);
|
||||
return ret;
|
||||
}
|
||||
this.rtfHTMLsplitRex = splitRexMaker(1);
|
||||
this.htmlRTFsplitRex = splitRexMaker(0);
|
||||
|
||||
// Create open-tag sniffing regexp
|
||||
function openSniffRexMaker(segment) {
|
||||
var rexes = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
|
||||
rexes[_rexData[i][0][segment][j].replace("\\", "\\\\")] = true;
|
||||
}
|
||||
}
|
||||
return composeRex(rexes);
|
||||
}
|
||||
this.rtfHTMLopenSniffRex = openSniffRexMaker(1);
|
||||
this.htmlRTFopenSniffRex = openSniffRexMaker(0);
|
||||
|
||||
// Create open-tag remapper
|
||||
function openTagRemapMaker(segment) {
|
||||
var ret = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
var master = _rexData[i][0][segment][0];
|
||||
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
|
||||
ret[_rexData[i][0][segment][j]] = master;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
this.rtfHTMLopenTagRemap = openTagRemapMaker(1);
|
||||
this.htmlRTFopenTagRemap = openTagRemapMaker(0);
|
||||
|
||||
// Create open-tag-keyed close-tag sniffing regexps
|
||||
function closeTagRexMaker(segment) {
|
||||
var ret = {};
|
||||
var rexes = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
var master = _rexData[i][0][segment][0];
|
||||
for (var j=0,jlen=_rexData[i][1][segment].length; j < jlen; j++) {
|
||||
rexes[_rexData[i][1][segment][j]] = true;
|
||||
}
|
||||
ret[master] = composeRex(rexes);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
this.rtfHTMLcloseTagRex = closeTagRexMaker(1);
|
||||
this.htmlRTFcloseTagRex = closeTagRexMaker(0);
|
||||
|
||||
// Create open-tag-keyed open/close tag registry
|
||||
function tagRegistryMaker(segment) {
|
||||
var antisegment = 1;
|
||||
if (segment == 1) {
|
||||
antisegment = 0;
|
||||
}
|
||||
var ret = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
var master = _rexData[i][0][segment][0];
|
||||
ret[master] = {
|
||||
open: _rexData[i][0][antisegment][0],
|
||||
close: _rexData[i][1][antisegment][0]
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
this.rtfHTMLtagRegistry = tagRegistryMaker(1);
|
||||
this.htmlRTFtagRegistry = tagRegistryMaker(0);
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
this.init();
|
||||
|
||||
this.getSplit = function(mode, txt) {
|
||||
if (!txt) return [];
|
||||
var splt = txt.split(this[mode + "splitRex"]);
|
||||
var mtch = txt.match(this[mode + "splitRex"]);
|
||||
var lst = [splt[0]];
|
||||
for (var i=1,ilen=splt.length; i < ilen; i++) {
|
||||
lst.push(mtch[i-1]);
|
||||
lst.push(splt[i]);
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
this.getOpenTag = function(mode, str) {
|
||||
var m = str.match(this[mode + "openSniffRex"]);
|
||||
if (m) {
|
||||
m = this[mode + "openTagRemap"][m[0]];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
this.convert = function(mode, txt) {
|
||||
var lst = this.getSplit(mode, txt);
|
||||
var sdepth = 0;
|
||||
var depth = 0;
|
||||
for (var i=1,ilen=lst.length; i < ilen; i += 2) {
|
||||
var openTag = this.getOpenTag(mode, lst[i]);
|
||||
if (openTag) {
|
||||
sdepth++;
|
||||
depth = sdepth;
|
||||
for (var j=(i+2),jlen=lst.length; j < jlen; j += 2) {
|
||||
var closeTag = !this.getOpenTag(mode, lst[j]);
|
||||
if (closeTag) {
|
||||
if (depth === sdepth && lst[j].match(this[mode + "closeTagRex"][openTag])) {
|
||||
lst[i] = this[mode + "tagRegistry"][openTag].open;
|
||||
lst[j] = this[mode + "tagRegistry"][openTag].close;
|
||||
break;
|
||||
}
|
||||
depth--;
|
||||
} else {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sdepth--;
|
||||
}
|
||||
}
|
||||
return lst.join("");
|
||||
}
|
||||
|
||||
this.htmlToRTF = function(txt) {
|
||||
// Catch this one before is clobbered by unescape
|
||||
txt = txt.replace(/<span class=\"tab\"> <\/span>/g, "\\tab{}");
|
||||
txt = Zotero.Utilities.unescapeHTML(txt);
|
||||
for (var i=0,ilen=this._htmlRTFmap.length; i < ilen; i++) {
|
||||
var entry = this._htmlRTFmap[i];
|
||||
txt = txt.replace(entry[0], entry[1]);
|
||||
}
|
||||
txt = this.convert("htmlRTF", txt);
|
||||
return txt.trim();
|
||||
}
|
||||
|
||||
this.rtfToHTML = function(txt) {
|
||||
for (var i=0,ilen=this._rtfHTMLmap.length; i < ilen; i++) {
|
||||
var entry = this._rtfHTMLmap[i];
|
||||
txt = txt.replace(entry[0], entry[1]);
|
||||
}
|
||||
txt = this.convert("rtfHTML", txt);
|
||||
return txt.trim();
|
||||
}
|
||||
|
||||
this._constructed = true;
|
||||
|
||||
// Don't load if a value hasn't yet been set
|
||||
if (this._loadOnConstruct) {
|
||||
this._load();
|
||||
}
|
||||
]]></constructor>
|
||||
|
||||
<property name="mode">
|
||||
<getter><![CDATA[
|
||||
if (!this._mode) {
|
||||
throw ("mode is not defined in styled-textbox.xml");
|
||||
}
|
||||
return this._mode;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
Zotero.debug("Setting mode to " + val);
|
||||
switch (val) {
|
||||
case 'note':
|
||||
var self = this;
|
||||
|
||||
this._eventHandler = function (event) {
|
||||
// Necessary in Fx32+
|
||||
if (event.wrappedJSObject) {
|
||||
event = event.wrappedJSObject;
|
||||
}
|
||||
|
||||
//Zotero.debug(event.type);
|
||||
switch (event.type) {
|
||||
case 'keydown':
|
||||
// Intercept and manually trigger redo for Cmd-Shift-Z,
|
||||
// which keeps it from toggling the Zotero pane instead
|
||||
if (Zotero.isMac && event.metaKey && event.shiftKey && !event.ctrlKey
|
||||
&& !event.altKey && event.keyCode == 90) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
self.redo();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'keypress':
|
||||
// Ignore keypresses that don't change
|
||||
// any text
|
||||
if (!event.which &&
|
||||
event.keyCode != event.DOM_VK_DELETE &&
|
||||
event.keyCode != event.DOM_VK_BACK_SPACE) {
|
||||
//Zotero.debug("Not a char");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'change':
|
||||
break;
|
||||
|
||||
case 'openlink':
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
win = wm.getMostRecentWindow('navigator:browser');
|
||||
win.ZoteroPane.loadURI(event.target.href, event.modifierKeys);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (self._timer) {
|
||||
clearTimeout(self._timer);
|
||||
}
|
||||
|
||||
// Get the command event
|
||||
self._timer = self.timeout && setTimeout(function () {
|
||||
var attr = self.getAttribute('oncommand');
|
||||
attr = attr.replace('this', 'thisObj');
|
||||
var func = new Function('thisObj', 'event', attr);
|
||||
func(self, event);
|
||||
}, self.timeout);
|
||||
|
||||
return true;
|
||||
};
|
||||
break;
|
||||
|
||||
case 'integration':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in styled-textbox.xml");
|
||||
}
|
||||
return this._mode = val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<!-- Sets or returns formatting (currently, HTML or Integration) of rich text box -->
|
||||
<property name="initialized">
|
||||
<getter><![CDATA[
|
||||
return !!this._editor;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- Sets or returns formatting (currently, HTML or Integration) of rich text box -->
|
||||
<property name="format">
|
||||
<getter><![CDATA[
|
||||
return this._format;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
return this._format = val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<!-- Sets or returns contents of rich text box -->
|
||||
<property name="value">
|
||||
<getter><![CDATA[
|
||||
var output = this._editor.getContent().trim();
|
||||
|
||||
if(this._format == "RTF") {
|
||||
// strip divs
|
||||
if(output.substr(0, 5) == "<div>" && output.substr(-6) == "</div>") {
|
||||
output = output.slice(0, output.length-6).slice(5).trim();
|
||||
}
|
||||
output = this.htmlToRTF(output)
|
||||
}
|
||||
|
||||
return output;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (self._timer) {
|
||||
clearTimeout(self._timer);
|
||||
}
|
||||
|
||||
if(!this._editor) {
|
||||
Zotero.debug('No editor yet');
|
||||
|
||||
this._value = val;
|
||||
if (!this._constructed) {
|
||||
Zotero.debug('Styled textbox not yet constructed', 2);
|
||||
this._loadOnConstruct = true;
|
||||
}
|
||||
else if (!this._loaded) {
|
||||
this._load();
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
if (this.value == val) {
|
||||
Zotero.debug("Textbox value hasn't changed");
|
||||
return;
|
||||
}
|
||||
|
||||
var html = val;
|
||||
if(this._format == "RTF") {
|
||||
var bodyStyle = "";
|
||||
if(html.substr(0, 3) == "\\li") {
|
||||
// try to show paragraph formatting
|
||||
var returnIndex = html.indexOf("\r\n");
|
||||
|
||||
var tags = html.substr(1, returnIndex).split("\\");
|
||||
html = html.substr(returnIndex+2);
|
||||
|
||||
for(var i=0; i<tags.length; i++) {
|
||||
var tagName = tags[i].substr(0, 2);
|
||||
var tagValue = tags[i].substring(2, tags[i].length-1);
|
||||
if(tagName == "li") {
|
||||
var li = parseInt(tagValue, 10);
|
||||
} else if(tagName == "fi") {
|
||||
var fi = parseInt(tagValue, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// don't negatively indent
|
||||
if(fi < 0 && li == 0) li = -fi;
|
||||
|
||||
bodyStyle = "margin-left:"+(li/20+6)+"pt;text-indent:"+(fi/20)+"pt;";
|
||||
}
|
||||
|
||||
html = this.rtfToHTML(html);
|
||||
|
||||
html = '<div style="'+bodyStyle+'"><p>'+html+"</p></div>";
|
||||
}
|
||||
|
||||
this._editor.setContent(html);
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="timeout"
|
||||
onset="this.setAttribute('timeout', val); return val;"
|
||||
onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._editor) {
|
||||
this._iframe.focus();
|
||||
this._editor.focus();
|
||||
this._focus = false;
|
||||
}
|
||||
else {
|
||||
this._focus = true;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="redo">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._editor.undoManager.redo();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="clearUndo">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._editor.undoManager.clear();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<field name="_loaded"/>
|
||||
<method name="_load">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._loaded = true;
|
||||
|
||||
// Unless we find a better way, use a separate HTML file
|
||||
// for read-only mode
|
||||
var htmlFile = this.mode + (this.getAttribute('readonly') != 'true' ? "" : "view");
|
||||
|
||||
var ios = Components.classes["@mozilla.org/network/io-service;1"].
|
||||
getService(Components.interfaces.nsIIOService);
|
||||
var uri = ios.newURI("resource://zotero/tinymce/" + htmlFile + ".html", null, null);
|
||||
|
||||
// Pass directionality (LTR/RTL) in URL
|
||||
uri.spec += "?dir=" + Zotero.dir;
|
||||
|
||||
Zotero.debug("Loading " + uri.spec);
|
||||
|
||||
// Register handler for deferred setting of content
|
||||
var self = this;
|
||||
var matchTo = null;
|
||||
var listener = function(e) {
|
||||
var win = self._iframe.contentWindow;
|
||||
var SJOW = win.wrappedJSObject;
|
||||
|
||||
// only fire if the target matches, or _zoteroMatchTo, which we set last
|
||||
// time the target matched, matches
|
||||
if(e.target !== self._iframe.contentDocument
|
||||
&& (!SJOW._zoteroMatchTo || SJOW._zoteroMatchTo !== matchTo)) return;
|
||||
|
||||
if (!SJOW.tinyMCE) {
|
||||
var exts = Zotero.getInstalledExtensions(function(exts) {
|
||||
for each(var ext in exts) {
|
||||
if (ext.indexOf('NoScript') != -1 && ext.indexOf('disabled') == -1) {
|
||||
var doc = win.document;
|
||||
var div = doc.getElementById('tinymce');
|
||||
var warning = doc.createElement('div');
|
||||
warning.id = 'noScriptWarning';
|
||||
var str = "The NoScript extension is preventing Zotero "
|
||||
+ "from displaying notes. To use NoScript and Zotero together, "
|
||||
+ "whitelist the 'file:' scheme in the NoScript preferences "
|
||||
+ "and restart " + Zotero.appName + ".";
|
||||
warning.appendChild(document.createTextNode(str));
|
||||
div.appendChild(warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SJOW.zoteroInit) {
|
||||
SJOW.zoteroInit = function(editor) {
|
||||
// Necessary in Fx32+
|
||||
if (editor.wrappedJSObject) {
|
||||
self._editor = editor.wrappedJSObject;
|
||||
}
|
||||
else {
|
||||
self._editor = editor;
|
||||
}
|
||||
if (self._value) {
|
||||
self.value = self._value;
|
||||
}
|
||||
if (self._focus) {
|
||||
self._iframe.focus();
|
||||
self._editor.focus();
|
||||
self._focus = false;
|
||||
}
|
||||
|
||||
// Add CSS rules to notes
|
||||
if (self.mode == 'note') {
|
||||
let fontSize = Zotero.Prefs.get('note.fontSize');
|
||||
// Fix empty old font prefs before a value was enforced
|
||||
if (fontSize < 6) {
|
||||
fontSize = 11;
|
||||
}
|
||||
var css = "body#zotero-tinymce-note.mceContentBody, "
|
||||
+ "body#zotero-tinymce-note.mceContentBody p, "
|
||||
+ "body#zotero-tinymce-note.mceContentBody th, "
|
||||
+ "body#zotero-tinymce-note.mceContentBody td, "
|
||||
+ "body#zotero-tinymce-note.mceContentBody pre { "
|
||||
+ "font-size: " + fontSize + "px; "
|
||||
+ "} "
|
||||
+ "body#zotero-tinymce-note.mceContentBody, "
|
||||
+ "body#zotero-tinymce-note.mceContentBody p { "
|
||||
+ "font-family: "
|
||||
+ Zotero.Prefs.get('note.fontFamily') + "; "
|
||||
+ "}"
|
||||
+ Zotero.Prefs.get('note.css');
|
||||
|
||||
var doc = editor.contentDocument;
|
||||
var head = doc.getElementsByTagName("head")[0];
|
||||
var style = doc.createElement("style");
|
||||
style.innerHTML = css;
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
// Dispatch a tinymceInitialized event
|
||||
var ev = document.createEvent('HTMLEvents');
|
||||
ev.initEvent('tinymceInitialized', true, true);
|
||||
self.dispatchEvent(ev);
|
||||
};
|
||||
}
|
||||
|
||||
var editor = SJOW.tinyMCE.get("tinymce");
|
||||
if (!editor) {
|
||||
Zotero.debug("editor not ready");
|
||||
|
||||
// this is a hack; I'm not sure why we can't identify the event target
|
||||
// next time without it, but apparently we can't
|
||||
matchTo = Zotero.randomString();
|
||||
SJOW._zoteroMatchTo = matchTo;
|
||||
|
||||
// Not ready yet
|
||||
return;
|
||||
}
|
||||
|
||||
if(window.ZoteroTab) {
|
||||
ZoteroTab.containerWindow.gBrowser.removeEventListener("DOMContentLoaded", listener, true);
|
||||
} else {
|
||||
self._iframe.removeEventListener("DOMContentLoaded", listener, false);
|
||||
}
|
||||
|
||||
if (self._eventHandler) {
|
||||
win.wrappedJSObject.zoteroHandleEvent = self._eventHandler;
|
||||
}
|
||||
|
||||
// Run Cut/Copy/Paste with chrome privileges
|
||||
win.wrappedJSObject.zoteroExecCommand = function (doc, command, ui, value) {
|
||||
return doc.execCommand(command, ui, value);
|
||||
}
|
||||
|
||||
win.wrappedJSObject.zoteroFixWindow = function (win) {
|
||||
win.locationbar.visible = false;
|
||||
win.statusbar.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
if(window.ZoteroTab) {
|
||||
// I'm not sure why it's necessary to attach the event listener to the
|
||||
// container window to get it to fire on the tab, but apparently it is...
|
||||
ZoteroTab.containerBrowser.addEventListener("DOMContentLoaded", listener, true);
|
||||
} else {
|
||||
this._iframe.addEventListener("DOMContentLoaded", listener, false);
|
||||
}
|
||||
|
||||
this._iframe.webNavigation.loadURI(uri.spec,
|
||||
Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, null, null, null);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:iframe flex="1" anonid="rt-view" class="rt-view" type="content"
|
||||
xbl:inherits="onfocus,onblur,flex,width,height,hidden"
|
||||
style="overflow: hidden"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
1088
chrome/content/zotero/bindings/tagsbox.xml
Normal file
1051
chrome/content/zotero/bindings/tagselector.xml
Normal file
129
chrome/content/zotero/bindings/text-link.xml
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Toolkit.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** -->
|
||||
<bindings id="textBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<binding id="text-link" extends="chrome://global/content/bindings/text.xml#text-label">
|
||||
<implementation implements="nsIAccessibleProvider">
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return Components.interfaces.nsIAccessibleProvider.XULLink;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<property name="href" onget="return this.getAttribute('href');"
|
||||
onset="this.setAttribute('href', val); return val;" />
|
||||
<method name="open">
|
||||
<parameter name="aEvent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var href = this.href;
|
||||
if (!href || this.disabled || aEvent.getPreventDefault())
|
||||
return;
|
||||
|
||||
var uri = null;
|
||||
try {
|
||||
const nsISSM = Components.interfaces.nsIScriptSecurityManager;
|
||||
const secMan =
|
||||
Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(nsISSM);
|
||||
|
||||
const ioService =
|
||||
Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
|
||||
uri = ioService.newURI(href, null, null);
|
||||
|
||||
var nullPrincipal =
|
||||
Components.classes["@mozilla.org/nullprincipal;1"]
|
||||
.createInstance(Components.interfaces.nsIPrincipal);
|
||||
try {
|
||||
secMan.checkLoadURIWithPrincipal(nullPrincipal, uri,
|
||||
nsISSM.DISALLOW_INHERIT_PRINCIPAL)
|
||||
}
|
||||
catch (ex) {
|
||||
var msg = "Error: Cannot open a " + uri.scheme + ": link using \
|
||||
the text-link binding.";
|
||||
Components.utils.reportError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const cID = "@mozilla.org/uriloader/external-protocol-service;1";
|
||||
const nsIEPS = Components.interfaces.nsIExternalProtocolService;
|
||||
var protocolSvc = Components.classes[cID].getService(nsIEPS);
|
||||
|
||||
// if the scheme is not an exposed protocol, then opening this link
|
||||
// should be deferred to the system's external protocol handler
|
||||
if (!protocolSvc.isExposedProtocol(uri.scheme)
|
||||
|| (window.Zotero && window.Zotero.isStandalone && ["http", "https"].indexOf(uri.scheme) !== -1)) {
|
||||
protocolSvc.loadUrl(uri);
|
||||
aEvent.preventDefault()
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
catch (ex) {
|
||||
Components.utils.reportError(ex);
|
||||
}
|
||||
|
||||
// otherwise, fall back to opening the anchor directly
|
||||
var win = window;
|
||||
if (window instanceof Components.interfaces.nsIDOMChromeWindow) {
|
||||
while (win.opener && !win.opener.closed)
|
||||
win = win.opener;
|
||||
}
|
||||
|
||||
if (uri)
|
||||
win.open(uri.spec);
|
||||
else
|
||||
win.open(href);
|
||||
|
||||
aEvent.preventDefault();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="click" phase="capturing" button="0" action="this.open(event)"/>
|
||||
<handler event="keypress" preventdefault="true" keycode="VK_ENTER" action="this.click()" />
|
||||
<handler event="keypress" preventdefault="true" keycode="VK_RETURN" action="this.click()" />
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
293
chrome/content/zotero/bindings/timedtextarea.xml
Normal file
|
@ -0,0 +1,293 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
A combination of Mozilla's textarea, timed-textbox, input-box, and
|
||||
input-box-spell bindings, with the timed-textbox's Return key
|
||||
event handler removed
|
||||
|
||||
Note: It would be much nicer if a) Mozilla offered this natively or
|
||||
b) we just extended the timed-textbox binding directly, but since it's based
|
||||
on html:input rather than html:textarea, doing so breaks things in various
|
||||
ways (though it may be possible with some tweaking)
|
||||
|
||||
Also note: spellcheck code here is a slightly adjusted version
|
||||
of a patch by Neil Deakin on Bugzilla that wasn't approved in time for
|
||||
Firefox 2.0 (https://bugzilla.mozilla.org/show_bug.cgi?id=346787).
|
||||
When there's native support for spellcheck="true" in XUL, we'll hopefully be
|
||||
able to use that, though it'll still need to work as a timed textarea...
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings [
|
||||
<!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" >
|
||||
%textcontextDTD;
|
||||
|
||||
<!-- These aren't yet included in textcontext.dtd in Minefield, so we reproduce them here
|
||||
(rather than including the massive browser.dtd) -->
|
||||
<!ENTITY spellAddToDictionary.label "Add to dictionary">
|
||||
<!ENTITY spellAddToDictionary.accesskey "o">
|
||||
<!ENTITY spellEnable.label "Spell check this field">
|
||||
<!ENTITY spellEnable.accesskey "S">
|
||||
<!ENTITY spellNoSuggestions.label "(No spelling suggestions)">
|
||||
<!ENTITY spellDictionaries.label "Languages">
|
||||
<!ENTITY spellDictionaries.accesskey "l">
|
||||
<!ENTITY spellAddDictionaries.label "Add dictionaries...">
|
||||
<!ENTITY spellAddDictionaries.accesskey "A">
|
||||
]>
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<binding id="timed-textarea" extends="chrome://global/content/bindings/textbox.xml#textbox">
|
||||
<implementation>
|
||||
<field name="mInputField">null</field>
|
||||
<property name="inputField" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (!this.mInputField)
|
||||
this.mInputField = document.getAnonymousElementByAttribute(this, "anonid", "input");
|
||||
return this.mInputField;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<field name="_timer">null</field>
|
||||
<property name="timeout"
|
||||
onset="this.setAttribute('timeout', val); return val;"
|
||||
onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
|
||||
<property name="value">
|
||||
<getter>
|
||||
return this.inputField.value;
|
||||
</getter>
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.inputField.value = val;
|
||||
if (this._timer)
|
||||
clearTimeout(this._timer);
|
||||
return val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<method name="_fireCommand">
|
||||
<parameter name="me"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
me._timer = null;
|
||||
me.doCommand();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<!-- Spellcheck code -->
|
||||
<field name="_spellCheckInitialized">false</field>
|
||||
<property name="spellCheckerUI" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (!this._spellCheckInitialized) {
|
||||
this._spellCheckInitialized = true;
|
||||
|
||||
const CI = Components.interfaces;
|
||||
if (!document instanceof CI.nsIDOMXULDocument)
|
||||
return null;
|
||||
|
||||
var textbox = this;
|
||||
|
||||
if (!textbox || !textbox instanceof CI.nsIDOMXULTextBoxElement)
|
||||
return null;
|
||||
|
||||
try {
|
||||
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].
|
||||
getService(CI.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript("chrome://global/content/inlineSpellCheckUI.js", this);
|
||||
|
||||
if ("InlineSpellCheckerUI" in this)
|
||||
this.InlineSpellCheckerUI.init(
|
||||
textbox.inputField.QueryInterface(CI.nsIDOMNSEditableElement).editor
|
||||
);
|
||||
} catch(ex) {
|
||||
// this throws an error on window open...
|
||||
}
|
||||
}
|
||||
|
||||
return this.InlineSpellCheckerUI;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
// can't initialize the spell checker in the constructor as not
|
||||
// everything is initialized and the editor will fail to create the
|
||||
// inline spell checker object
|
||||
setTimeout(this._delayedInitSpellCheck, 0, this)
|
||||
|
||||
// oninput doesn't seem to fire on text drag
|
||||
this.inputField.addEventListener('dragdrop', function(event) {
|
||||
document.getBindingParent(event.target).doInput();
|
||||
}, false);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<method name="_delayedInitSpellCheck">
|
||||
<parameter name="me"/>
|
||||
<body><![CDATA[
|
||||
var spellui = me.spellCheckerUI;
|
||||
if (spellui)
|
||||
spellui.enabled = true;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_doPopupItemEnabling">
|
||||
<parameter name="popupNode"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var children = popupNode.childNodes;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var command = children[i].getAttribute("cmd");
|
||||
if (command) {
|
||||
var controller = document.commandDispatcher.getControllerForCommand(command);
|
||||
var enabled = controller.isCommandEnabled(command);
|
||||
if (enabled) {
|
||||
children[i].removeAttribute("disabled");
|
||||
}
|
||||
else {
|
||||
children[i].setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_doPopupItemEnablingSpell">
|
||||
<parameter name="popupNode"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var spellui = this.spellCheckerUI;
|
||||
if (!spellui || !spellui.canSpellCheck) {
|
||||
this._setMenuItemVisibility("spell-no-suggestions", false);
|
||||
this._setMenuItemVisibility("spell-check-enabled", false);
|
||||
this._setMenuItemVisibility("spell-check-separator", false);
|
||||
this._setMenuItemVisibility("spell-add-to-dictionary", false);
|
||||
this._setMenuItemVisibility("spell-suggestions-separator", false);
|
||||
this._setMenuItemVisibility("spell-dictionaries", false);
|
||||
return;
|
||||
}
|
||||
|
||||
spellui.initFromEvent(document.popupRangeParent,
|
||||
document.popupRangeOffset);
|
||||
|
||||
var enabled = spellui.enabled;
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"spell-check-enabled").setAttribute("checked", enabled);
|
||||
|
||||
var overMisspelling = spellui.overMisspelling;
|
||||
this._setMenuItemVisibility("spell-add-to-dictionary", overMisspelling);
|
||||
this._setMenuItemVisibility("spell-suggestions-separator", overMisspelling);
|
||||
|
||||
// suggestion list
|
||||
var suggestionsSeparator = document.getAnonymousElementByAttribute(this,
|
||||
"anonid", "spell-add-to-dictionary");
|
||||
var numsug = spellui.addSuggestionsToMenu(popupNode, suggestionsSeparator, 5);
|
||||
this._setMenuItemVisibility("spell-no-suggestions", overMisspelling && numsug == 0);
|
||||
|
||||
// dictionary list
|
||||
var dictmenu = document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"spell-dictionaries-menu");
|
||||
var addsep = document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"spell-language-separator");
|
||||
|
||||
var numdicts = spellui.addDictionaryListToMenu(dictmenu, addsep);
|
||||
this._setMenuItemVisibility("spell-dictionaries", enabled);
|
||||
|
||||
this._doPopupItemEnabling(popupNode);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_doPopupItemDisabling">
|
||||
<body><![CDATA[
|
||||
if (this.spellCheckerUI) {
|
||||
this.spellCheckerUI.clearSuggestionsFromMenu();
|
||||
this.spellCheckerUI.clearDictionaryListFromMenu();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_setMenuItemVisibility">
|
||||
<parameter name="anonid"/>
|
||||
<parameter name="visible"/>
|
||||
<body><![CDATA[
|
||||
document.getAnonymousElementByAttribute(this, "anonid", anonid).
|
||||
hidden = ! visible;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="doTextCommand">
|
||||
<parameter name="command"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var controller = document.commandDispatcher.getControllerForCommand(command);
|
||||
controller.doCommand(command);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="doInput">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
|
||||
<handlers>
|
||||
<handler event="input">
|
||||
<![CDATA[
|
||||
this.doInput();
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
|
||||
|
||||
<content context="_child">
|
||||
<xul:hbox class="textbox-input-box" flex="1">
|
||||
<html:textarea class="textbox-textarea" flex="1" anonid="input"
|
||||
xbl:inherits="onfocus,onblur,xbl:text=value,disabled,tabindex,rows,cols,readonly,wrap"><children/></html:textarea>
|
||||
<xul:menupopup anonid="input-box-contextmenu"
|
||||
onpopupshowing="if (document.commandDispatcher.focusedElement != this.parentNode.firstChild) { this.parentNode.firstChild.focus(); } this.parentNode.parentNode._doPopupItemEnablingSpell(this);"
|
||||
onpopuphiding="this.parentNode.parentNode._doPopupItemDisabling(this);"
|
||||
oncommand="var cmd = event.originalTarget.getAttribute('cmd'); if(cmd) { this.parentNode.parentNode.doTextCommand(cmd); event.stopPropagation(); }">
|
||||
<xul:menuitem label="&spellNoSuggestions.label;" anonid="spell-no-suggestions" disabled="true"/>
|
||||
<xul:menuitem label="&spellAddToDictionary.label;" accesskey="&spellAddToDictionary.accesskey;" anonid="spell-add-to-dictionary"
|
||||
oncommand="this.parentNode.parentNode.parentNode.spellCheckerUI.addToDictionary();"/>
|
||||
<xul:menuseparator anonid="spell-suggestions-separator"/>
|
||||
<xul:menuitem label="&undoCmd.label;" accesskey="&undoCmd.accesskey;" cmd="cmd_undo"/>
|
||||
<xul:menuseparator/>
|
||||
<xul:menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;" cmd="cmd_cut"/>
|
||||
<xul:menuitem label="©Cmd.label;" accesskey="©Cmd.accesskey;" cmd="cmd_copy"/>
|
||||
<xul:menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" cmd="cmd_paste"/>
|
||||
<xul:menuitem label="&deleteCmd.label;" accesskey="&deleteCmd.accesskey;" cmd="cmd_delete"/>
|
||||
<xul:menuseparator/>
|
||||
<xul:menuitem label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;" cmd="cmd_selectAll"/>
|
||||
<xul:menuseparator anonid="spell-check-separator"/>
|
||||
<xul:menuitem label="&spellEnable.label;" type="checkbox" accesskey="&spellEnable.accesskey;" anonid="spell-check-enabled"
|
||||
oncommand="this.parentNode.parentNode.parentNode.spellCheckerUI.toggleEnabled();"/>
|
||||
<xul:menu label="&spellDictionaries.label;" accesskey="&spellDictionaries.accesskey;" anonid="spell-dictionaries">
|
||||
<xul:menupopup anonid="spell-dictionaries-menu"
|
||||
onpopupshowing="event.stopPropagation();"
|
||||
onpopuphiding="event.stopPropagation();">
|
||||
<xul:menuseparator anonid="spell-language-separator"/>
|
||||
<xul:menuitem anonid="spell-add-dictionaries-main" label="&spellAddDictionaries.label;"
|
||||
accesskey="&spellAddDictionaries.accesskey;"
|
||||
oncommand="nsContextMenu.prototype.addDictionaries();"/>
|
||||
</xul:menupopup>
|
||||
</xul:menu>
|
||||
</xul:menupopup>
|
||||
</xul:hbox>
|
||||
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
997
chrome/content/zotero/bindings/zoterosearch.xml
Normal file
|
@ -0,0 +1,997 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/searchbox.dtd">
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="search-box">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/search.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<field name="searchRef"/>
|
||||
<property name="search" onget="return this.searchRef;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.searchRef = val;
|
||||
|
||||
this.buildLibraryMenu();
|
||||
|
||||
var conditionsBox = this.id('conditions');
|
||||
while(conditionsBox.hasChildNodes())
|
||||
conditionsBox.removeChild(conditionsBox.firstChild);
|
||||
|
||||
var conditions = this.search.getSearchConditions();
|
||||
|
||||
for(var id in conditions)
|
||||
{
|
||||
// Checkboxes
|
||||
switch (conditions[id]['condition']) {
|
||||
case 'recursive':
|
||||
case 'noChildren':
|
||||
case 'includeParentsAndChildren':
|
||||
var checkbox = conditions[id]['condition'] + 'Checkbox';
|
||||
this.id(checkbox).setAttribute('condition',id);
|
||||
this.id(checkbox).checked = (conditions[id]['operator']=='true');
|
||||
continue;
|
||||
}
|
||||
|
||||
if(conditions[id]['condition'] == 'joinMode')
|
||||
{
|
||||
this.id('joinModeMenu').setAttribute('condition',id);
|
||||
this.id('joinModeMenu').value = conditions[id]['operator'];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.addCondition(conditions[id]);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<method name="buildLibraryMenu">
|
||||
<body><![CDATA[
|
||||
var menulist = this.id('libraryMenu');
|
||||
var menupopup = menulist.firstChild;
|
||||
|
||||
while (menupopup.hasChildNodes()) {
|
||||
menupopup.removeChild(menupopup.firstChild);
|
||||
}
|
||||
|
||||
var libraryID = this.searchRef.libraryID;
|
||||
var libraryIndex = 0;
|
||||
|
||||
// Add My Library
|
||||
var menuitem = document.createElement('menuitem');
|
||||
menuitem.setAttribute('label', Zotero.getString('pane.collections.library'));
|
||||
menuitem.setAttribute('libraryID', 0);
|
||||
menupopup.appendChild(menuitem);
|
||||
|
||||
// Add groups
|
||||
var groups = Zotero.Groups.getAll();
|
||||
for (let i=0; i<groups.length; i++) {
|
||||
let group = groups[i];
|
||||
let menuitem = document.createElement('menuitem');
|
||||
menuitem.setAttribute('label', group.name);
|
||||
menuitem.setAttribute('libraryID', group.libraryID);
|
||||
if (group.libraryID == libraryID) {
|
||||
libraryIndex = i + 1;
|
||||
}
|
||||
menupopup.appendChild(menuitem);
|
||||
}
|
||||
|
||||
menulist.appendChild(menupopup);
|
||||
menulist.selectedIndex = libraryIndex;
|
||||
|
||||
if (this.searchRef.id) {
|
||||
this.id('libraryMenu').disabled = true;
|
||||
}
|
||||
|
||||
this.updateLibrary();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="addCondition">
|
||||
<parameter name="ref"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var conditionsBox = this.id('conditions');
|
||||
var condition = document.createElement('zoterosearchcondition');
|
||||
condition.setAttribute('flex','1');
|
||||
|
||||
conditionsBox.appendChild(condition);
|
||||
|
||||
// Default to an empty 'title' condition
|
||||
if (!ref) {
|
||||
ref = this.search.getSearchCondition(this.search.addCondition("title","contains",""))
|
||||
}
|
||||
|
||||
condition.initWithParentAndCondition(this, ref);
|
||||
|
||||
if (conditionsBox.childNodes.length == 2){
|
||||
conditionsBox.childNodes[0].enableRemoveButton();
|
||||
}
|
||||
else if (conditionsBox.childNodes.length == 1){
|
||||
conditionsBox.childNodes[0].disableRemoveButton();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeCondition">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var conditionsBox = this.id('conditions');
|
||||
|
||||
this.search.removeCondition(id);
|
||||
|
||||
for (var i = 0, len=conditionsBox.childNodes.length; i < len; i++){
|
||||
if (conditionsBox.childNodes[i].conditionID == id){
|
||||
conditionsBox.removeChild(conditionsBox.childNodes[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (conditionsBox.childNodes.length == 1){
|
||||
conditionsBox.childNodes[0].disableRemoveButton();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="updateLibrary">
|
||||
<body><![CDATA[
|
||||
var menu = this.id('libraryMenu');
|
||||
var libraryID = parseInt(menu.selectedItem.getAttribute('libraryID'));
|
||||
|
||||
if (this.onLibraryChange) {
|
||||
this.onLibraryChange(libraryID);
|
||||
}
|
||||
|
||||
// TODO: libraryIDInt
|
||||
this.searchRef.libraryID = libraryID ? libraryID : null;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateJoinMode">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var menu = this.id('joinModeMenu');
|
||||
if(menu.hasAttribute('condition'))
|
||||
this.search.updateCondition(menu.getAttribute('condition'),'joinMode',menu.value,null);
|
||||
else
|
||||
menu.setAttribute('condition', this.search.addCondition('joinMode',menu.value,null));
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="updateCheckbox">
|
||||
<parameter name="condition"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var checkbox = this.id(condition + 'Checkbox');
|
||||
var value = checkbox.checked ? 'true' : 'false';
|
||||
if(checkbox.hasAttribute('condition'))
|
||||
{
|
||||
this.search.updateCondition(checkbox.getAttribute('condition'),
|
||||
condition, value, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkbox.setAttribute('condition',
|
||||
this.search.addCondition(condition, value, null));
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Calls updateSearch() on all search conditions -->
|
||||
<method name="updateSearch">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var conditionsBox = this.id('conditions');
|
||||
if (conditionsBox.hasChildNodes()) {
|
||||
for(var i = 0, len=conditionsBox.childNodes.length; i < len; i++) {
|
||||
conditionsBox.childNodes[i].updateSearch();
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="save">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.updateSearch();
|
||||
return this.search.save(true);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="handleKeyPress">
|
||||
<parameter name="event"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
switch (event.keyCode) {
|
||||
case event.DOM_VK_RETURN:
|
||||
case event.DOM_VK_ENTER:
|
||||
this.active = true;
|
||||
|
||||
if (event.shiftKey) {
|
||||
this.addCondition();
|
||||
}
|
||||
else {
|
||||
this.doCommand();
|
||||
}
|
||||
break;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="search-box" flex="1" onkeypress="document.getBindingParent(this).handleKeyPress(event)">
|
||||
<hbox align="center">
|
||||
<label value="&zotero.search.searchInLibrary;" control="libraryMenu"/>
|
||||
<menulist id="libraryMenu" oncommand="document.getBindingParent(this).updateLibrary();">
|
||||
<menupopup/>
|
||||
</menulist>
|
||||
</hbox>
|
||||
<groupbox xbl:inherits="flex">
|
||||
<caption align="center">
|
||||
<label value="&zotero.search.joinMode.prefix;"/>
|
||||
<menulist id="joinModeMenu" oncommand="document.getBindingParent(this).updateJoinMode();">
|
||||
<menupopup>
|
||||
<menuitem label="&zotero.search.joinMode.any;" value="any"/>
|
||||
<menuitem label="&zotero.search.joinMode.all;" value="all" selected="true"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<label value="&zotero.search.joinMode.suffix;"/>
|
||||
</caption>
|
||||
<vbox id="conditions"/>
|
||||
</groupbox>
|
||||
<hbox>
|
||||
<checkbox id="recursiveCheckbox" label="&zotero.search.recursive.label;" oncommand="document.getBindingParent(this).updateCheckbox('recursive');"/>
|
||||
<checkbox id="noChildrenCheckbox" label="&zotero.search.noChildren;" oncommand="document.getBindingParent(this).updateCheckbox('noChildren');"/>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<checkbox id="includeParentsAndChildrenCheckbox" label="&zotero.search.includeParentsAndChildren;" oncommand="document.getBindingParent(this).updateCheckbox('includeParentsAndChildren');"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
|
||||
<binding id="search-condition">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/search.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<field name="conditionID"/>
|
||||
<field name="selectedCondition"/>
|
||||
<field name="mode"/>
|
||||
<field name="selectedOperator"/>
|
||||
<field name="value"/>
|
||||
<field name="parent"/>
|
||||
<field name="dontupdate"/>
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
var operators = new Array('is', 'isNot', 'beginsWith', 'contains', 'doesNotContain', 'isLessThan', 'isGreaterThan', 'isBefore', 'isAfter', 'isInTheLast');
|
||||
var operatorsList = this.id('operatorsmenu');
|
||||
|
||||
// Build operator menu
|
||||
for(var i in operators)
|
||||
{
|
||||
operatorsList.appendItem(Zotero.getString('searchOperator.'+operators[i]),operators[i]);
|
||||
}
|
||||
|
||||
// Build conditions menu
|
||||
var conditionsList = this.id('conditionsmenu');
|
||||
var conditions = Zotero.SearchConditions.getStandardConditions();
|
||||
|
||||
for (var i=0, len=conditions.length; i<len; i++) {
|
||||
var menuitem = conditionsList.appendItem(conditions[i]['localized'], conditions[i]['name']);
|
||||
|
||||
var baseFields = null;
|
||||
try {
|
||||
baseFields = Zotero.ItemFields.getTypeFieldsFromBase(conditions[i]['name']);
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
// Add tooltip, building it if it doesn't exist
|
||||
if (baseFields) {
|
||||
if (!this.id(conditions[i]['name'] + '-tooltip')) {
|
||||
var fieldName = null;
|
||||
try {
|
||||
fieldName = Zotero.ItemFields.getLocalizedString(null, conditions[i].name);
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
if (fieldName) {
|
||||
var localized = [fieldName];
|
||||
}
|
||||
else {
|
||||
var localized = [];
|
||||
}
|
||||
|
||||
for (var j in baseFields) {
|
||||
var str = Zotero.SearchConditions.getLocalizedName(Zotero.ItemFields.getName(baseFields[j]));
|
||||
|
||||
if (localized.indexOf(str) == -1) {
|
||||
localized.push(str);
|
||||
}
|
||||
}
|
||||
localized.sort();
|
||||
|
||||
var tt = document.createElement('tooltip');
|
||||
tt.setAttribute('id', conditions[i]['name'] + '-tooltip');
|
||||
tt.setAttribute('orient', 'vertical');
|
||||
tt.setAttribute('noautohide', true);
|
||||
|
||||
var grid = document.createElement('grid');
|
||||
|
||||
var columns = document.createElement('columns');
|
||||
var col1 = document.createElement('column');
|
||||
var col2 = document.createElement('column');
|
||||
columns.appendChild(col1);
|
||||
columns.appendChild(col2);
|
||||
|
||||
var rows = document.createElement('rows');
|
||||
|
||||
var fieldRow = document.createElement('row');
|
||||
var label = document.createElement('label');
|
||||
label.setAttribute('value', Zotero.getString('searchConditions.tooltip.fields'));
|
||||
fieldRow.appendChild(label);
|
||||
var vbox = document.createElement('vbox');
|
||||
for each(var str in localized) {
|
||||
var label = document.createElement('label')
|
||||
label.setAttribute('value', str);
|
||||
vbox.appendChild(label);
|
||||
}
|
||||
fieldRow.appendChild(vbox);
|
||||
|
||||
rows.appendChild(fieldRow);
|
||||
|
||||
grid.appendChild(rows);
|
||||
tt.appendChild(grid);
|
||||
|
||||
this.id('condition-tooltips').appendChild(tt);
|
||||
}
|
||||
|
||||
menuitem.setAttribute('tooltip', conditions[i]['name'] + '-tooltip');
|
||||
}
|
||||
}
|
||||
conditionsList.selectedIndex = 0;
|
||||
]]>
|
||||
</constructor>
|
||||
<method name="onConditionSelected">
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Skip if correct condition already selected
|
||||
if (this.id('conditionsmenu').value==this.selectedCondition){
|
||||
return;
|
||||
}
|
||||
var conditionsMenu = this.id('conditionsmenu');
|
||||
var operatorsList = this.id('operatorsmenu');
|
||||
|
||||
this.selectedCondition = conditionsMenu.value;
|
||||
this.selectedOperator = operatorsList.value;
|
||||
|
||||
var condition = Zotero.SearchConditions.get(conditionsMenu.value);
|
||||
var operators = condition['operators'];
|
||||
|
||||
// Display appropriate operators for condition
|
||||
var selectThis;
|
||||
for(var i = 0, len = operatorsList.firstChild.childNodes.length; i < len; i++)
|
||||
{
|
||||
var val = operatorsList.firstChild.childNodes[i].getAttribute('value');
|
||||
var hidden = !operators[val];
|
||||
operatorsList.firstChild.childNodes[i].setAttribute('hidden', hidden);
|
||||
if (!hidden && (selectThis == null || this.selectedOperator == val))
|
||||
{
|
||||
selectThis = i;
|
||||
}
|
||||
}
|
||||
operatorsList.selectedIndex = selectThis;
|
||||
|
||||
// Generate drop-down menu instead of textbox for certain conditions
|
||||
switch (conditionsMenu.value){
|
||||
case 'collection':
|
||||
var rows = [];
|
||||
|
||||
var libraryID = this.parent.search.libraryID;
|
||||
libraryID = libraryID ? libraryID : null;
|
||||
var cols = Zotero.getCollections(false, true, libraryID);
|
||||
for (var i in cols) {
|
||||
// Indent subcollections
|
||||
var indent = '';
|
||||
if (cols[i].level) {
|
||||
for (var j=1; j<cols[i].level; j++) {
|
||||
indent += ' ';
|
||||
}
|
||||
indent += '- ';
|
||||
}
|
||||
rows.push([indent + cols[i].name, 'C' + Zotero.Collections.getLibraryKeyHash(cols[i])]);
|
||||
}
|
||||
this.createValueMenu(rows);
|
||||
break;
|
||||
|
||||
case 'savedSearch':
|
||||
var rows = [];
|
||||
var libraryID = this.parent.search.libraryID;
|
||||
libraryID = libraryID ? libraryID : null;
|
||||
var searches = Zotero.Searches.getAll(libraryID);
|
||||
for (var i in searches) {
|
||||
if (searches[i].id != this.parent.search.id) {
|
||||
rows.push([searches[i].name, 'S' + Zotero.Searches.getLibraryKeyHash(searches[i])]);
|
||||
}
|
||||
}
|
||||
this.createValueMenu(rows);
|
||||
break;
|
||||
|
||||
case 'itemType':
|
||||
var t = Zotero.ItemTypes.getTypes();
|
||||
|
||||
// Sort by localized name
|
||||
var types = [];
|
||||
for (var i=0; i<t.length; i++) {
|
||||
types.push({
|
||||
id: t[i].id,
|
||||
name: t[i].name,
|
||||
localized: Zotero.ItemTypes.getLocalizedString(t[i].id)
|
||||
});
|
||||
}
|
||||
var collation = Zotero.getLocaleCollation();
|
||||
types.sort(function(a, b) {
|
||||
return collation.compareString(1, a.localized, b.localized);
|
||||
});
|
||||
|
||||
for (var i in types) {
|
||||
types[i][0] = types[i].localized;
|
||||
types[i][1] = types[i].name;
|
||||
delete types[i]['name'];
|
||||
delete types[i]['id'];
|
||||
}
|
||||
this.createValueMenu(types);
|
||||
break;
|
||||
|
||||
case 'fileTypeID':
|
||||
var types = Zotero.FileTypes.getTypes();
|
||||
for (var i in types) {
|
||||
types[i][0] = Zotero.getString('fileTypes.' + types[i]['name']);
|
||||
types[i][1] = types[i]['id'];
|
||||
delete types[i]['name'];
|
||||
delete types[i]['id'];
|
||||
}
|
||||
this.createValueMenu(types);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (operatorsList.value=='isInTheLast')
|
||||
{
|
||||
this.id('value-date-age').value = this.value;
|
||||
}
|
||||
|
||||
// Textbox
|
||||
else {
|
||||
// If switching from menu to textbox, clear value
|
||||
if (this.id('valuefield').hidden){
|
||||
this.id('valuefield').value = '';
|
||||
}
|
||||
// If switching between textbox conditions, get loaded value for new one
|
||||
else {
|
||||
this.id('valuefield').value = this.value;
|
||||
}
|
||||
|
||||
// Update field drop-down if applicable
|
||||
this.id('valuefield').update(conditionsMenu.value, this.mode);
|
||||
}
|
||||
}
|
||||
|
||||
this.onOperatorSelected();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="onOperatorSelected">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var conditionsMenu = this.id('conditionsmenu');
|
||||
var operatorsList = this.id('operatorsmenu');
|
||||
|
||||
// Drop-down menu
|
||||
if (conditionsMenu.value == 'collection'
|
||||
|| conditionsMenu.value == 'savedSearch'
|
||||
|| conditionsMenu.value == 'itemType'
|
||||
|| conditionsMenu.value == 'fileTypeID') {
|
||||
this.id('valuefield').hidden = true;
|
||||
this.id('valuemenu').hidden = false;
|
||||
this.id('value-date-age').hidden = true;
|
||||
}
|
||||
|
||||
// Textbox + units dropdown for isInTheLast operator
|
||||
else if (operatorsList.value=='isInTheLast')
|
||||
{
|
||||
// If switching from text field, clear value
|
||||
if (this.id('value-date-age').hidden){
|
||||
this.value = '';
|
||||
}
|
||||
this.id('valuefield').hidden = true;
|
||||
this.id('valuemenu').hidden = true;
|
||||
this.id('value-date-age').hidden = false;
|
||||
}
|
||||
|
||||
// Textbox
|
||||
else
|
||||
{
|
||||
// If switching from date age, clear value
|
||||
if (this.id('valuefield').hidden){
|
||||
this.value = '';
|
||||
}
|
||||
this.id('valuefield').hidden = false;
|
||||
this.id('valuemenu').hidden = true;
|
||||
this.id('value-date-age').hidden = true;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="createValueMenu">
|
||||
<parameter name="values"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
while (this.id('valuemenu').hasChildNodes()){
|
||||
this.id('valuemenu').removeChild(this.id('valuemenu').firstChild);
|
||||
}
|
||||
|
||||
if (values.length){
|
||||
for (var i in values){
|
||||
this.id('valuemenu').appendItem(values[i][0], values[i][1]);
|
||||
}
|
||||
this.id('valuemenu').selectedIndex = 0;
|
||||
}
|
||||
|
||||
if (this.value)
|
||||
{
|
||||
this.id('valuemenu').value = this.value;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="initWithParentAndCondition">
|
||||
<parameter name="parent"/>
|
||||
<parameter name="condition"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.parent = parent;
|
||||
this.conditionID = condition['id'];
|
||||
|
||||
if(this.parent.search)
|
||||
{
|
||||
this.dontupdate = true; //so that the search doesn't get updated while we are creating controls.
|
||||
var prefix = '';
|
||||
|
||||
// Handle special conditions
|
||||
switch (condition.condition) {
|
||||
case 'savedSearch':
|
||||
prefix = 'S';
|
||||
break;
|
||||
|
||||
case 'collection':
|
||||
prefix = 'C';
|
||||
break;
|
||||
}
|
||||
|
||||
this.id('conditionsmenu').value = condition.condition;
|
||||
|
||||
// Convert datetimes from UTC to localtime
|
||||
if ((condition['condition']=='accessDate' ||
|
||||
condition['condition']=='dateAdded' ||
|
||||
condition['condition']=='dateModified') &&
|
||||
Zotero.Date.isSQLDateTime(condition['value'])){
|
||||
|
||||
condition['value'] =
|
||||
Zotero.Date.dateToSQL(Zotero.Date.sqlToDate(condition['value'], true));
|
||||
}
|
||||
|
||||
this.mode = condition['mode'];
|
||||
this.id('operatorsmenu').value = condition['operator'];
|
||||
this.value = prefix +
|
||||
(condition.value ? condition.value : '');
|
||||
|
||||
this.dontupdate = false;
|
||||
}
|
||||
|
||||
this.onConditionSelected();
|
||||
|
||||
this.id('conditionsmenu').focus();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<!-- Gets the value from the field and updates the associated search condition -->
|
||||
<method name="updateSearch">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if(this.parent && this.parent.search && !this.dontupdate)
|
||||
{
|
||||
var condition = this.id('conditionsmenu').value;
|
||||
var operator = this.id('operatorsmenu').value;
|
||||
|
||||
// Regular text field
|
||||
if (!this.id('valuefield').hidden)
|
||||
{
|
||||
var value = this.id('valuefield').value;
|
||||
|
||||
// Convert datetimes to UTC before saving
|
||||
switch (this.id('conditionsmenu').value) {
|
||||
case 'accessDate':
|
||||
case 'dateAdded':
|
||||
case 'dateModified':
|
||||
if (Zotero.Date.isSQLDateTime(value)) {
|
||||
var value = Zotero.Date.dateToSQL(Zotero.Date.sqlToDate(value), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Append mode to condition
|
||||
if (this.id('valuefield').mode){
|
||||
condition += '/' + this.id('valuefield').mode;
|
||||
}
|
||||
}
|
||||
|
||||
// isInTheLast operator
|
||||
else if (!this.id('value-date-age').hidden)
|
||||
{
|
||||
var value = this.id('value-date-age').value;
|
||||
}
|
||||
|
||||
// Handle special C1234 and S5678 form for
|
||||
// collections and searches
|
||||
else if (this.id('conditionsmenu').value == 'collection' || this.id('conditionsmenu').value == 'savedSearch')
|
||||
{
|
||||
var letter = this.id('valuemenu').value.substr(0,1);
|
||||
if (letter=='C')
|
||||
{
|
||||
condition = 'collection';
|
||||
}
|
||||
else if (letter=='S')
|
||||
{
|
||||
condition = 'savedSearch';
|
||||
}
|
||||
var value = this.id('valuemenu').value.substr(1);
|
||||
}
|
||||
|
||||
// Regular drop-down menu
|
||||
else
|
||||
{
|
||||
var value = this.id('valuemenu').value;
|
||||
}
|
||||
this.parent.search.updateCondition(this.conditionID, condition, operator, value);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="onRemoveClicked">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.parent){
|
||||
this.parent.removeCondition(this.conditionID);
|
||||
window.sizeToContent()
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="onAddClicked">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.parent){
|
||||
this.parent.addCondition();
|
||||
window.sizeToContent();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="disableRemoveButton">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var button = this.id("remove");
|
||||
button.setAttribute('disabled', true);
|
||||
button.removeAttribute('onclick');
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="enableRemoveButton">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var button = this.id("remove");
|
||||
button.setAttribute('disabled', false);
|
||||
button.setAttribute('onclick', "document.getBindingParent(this).onRemoveClicked(event)");
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var elems = document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id);
|
||||
return elems[0] ? elems[0] : false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:hbox id="search-condition" xbl:inherits="flex">
|
||||
<xul:popupset id="condition-tooltips"/>
|
||||
|
||||
<xul:menulist id="conditionsmenu" oncommand="document.getBindingParent(this).onConditionSelected(); event.stopPropagation()">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
<xul:menulist id="operatorsmenu" oncommand="document.getBindingParent(this).onOperatorSelected(); event.stopPropagation()">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
<xul:zoterosearchtextbox id="valuefield" flex="1"/>
|
||||
<xul:menulist id="valuemenu" flex="1" hidden="true">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
<xul:zoterosearchagefield id="value-date-age" hidden="true" flex="1"/>
|
||||
<xul:label id="remove" class="zotero-clicky zotero-clicky-minus" value="-" onclick="document.getBindingParent(this).onRemoveClicked(event)"/>
|
||||
<xul:label id="add" class="zotero-clicky zotero-clicky-plus" value="+" onclick="document.getBindingParent(this).onAddClicked(event)"/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
|
||||
<binding id="search-textbox">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/search.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<property name="value"
|
||||
onget="return document.getAnonymousNodes(this)[0].value"
|
||||
onset="document.getAnonymousNodes(this)[0].setAttribute('value', val); return val"/>
|
||||
<property name="mode">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (this.getAttribute('hasOptions')!='true'){
|
||||
return false;
|
||||
}
|
||||
|
||||
var button = this.id('textbox-button');
|
||||
var menu = this.id(button.popup);
|
||||
|
||||
var selectedIndex = -1;
|
||||
for (var i=0; i<menu.childNodes.length; i++){
|
||||
if (menu.childNodes[i].getAttribute('checked')=='true'){
|
||||
selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (button.popup){
|
||||
case 'textbox-fulltext-menu':
|
||||
switch (selectedIndex){
|
||||
case 0:
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
return 'phraseBinary';
|
||||
|
||||
case 2:
|
||||
return 'regexp';
|
||||
|
||||
case 3:
|
||||
return 'regexpCS';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
throw('Invalid search textbox popup');
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<method name="update">
|
||||
<parameter name="condition"/>
|
||||
<parameter name="mode"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var button = this.id('textbox-button');
|
||||
|
||||
switch (condition){
|
||||
case 'fulltextContent':
|
||||
button.popup = 'textbox-fulltext-menu';
|
||||
button.setAttribute('popup', 'textbox-fulltext-menu');
|
||||
var menu = this.id(button.popup);
|
||||
this.setAttribute('hasOptions', true);
|
||||
|
||||
var selectedIndex = 0;
|
||||
if (mode){
|
||||
switch (mode){
|
||||
case 'phrase':
|
||||
selectedIndex = 0;
|
||||
break;
|
||||
|
||||
case 'phraseBinary':
|
||||
selectedIndex = 1;
|
||||
break;
|
||||
|
||||
case 'regexp':
|
||||
selectedIndex = 2;
|
||||
break;
|
||||
|
||||
case 'regexpCS':
|
||||
selectedIndex = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
menu.childNodes[selectedIndex].setAttribute('checked', true);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.setAttribute('hasOptions', false);
|
||||
|
||||
// Set textbox to autocomplete mode
|
||||
switch (condition)
|
||||
{
|
||||
// Skip autocomplete for these fields
|
||||
case 'date':
|
||||
case 'note':
|
||||
case 'extra':
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
var textbox = document.getAnonymousNodes(this)[0];
|
||||
textbox.setAttribute('type', 'autocomplete');
|
||||
textbox.setAttribute('autocompletesearch', 'zotero');
|
||||
textbox.setAttribute('timeout', '250');
|
||||
|
||||
var autocompleteParams = {
|
||||
fieldName: condition
|
||||
};
|
||||
if (condition == 'creator') {
|
||||
autocompleteParams.fieldMode = 2;
|
||||
}
|
||||
textbox.setAttribute(
|
||||
'autocompletesearchparam',
|
||||
JSON.stringify(autocompleteParams)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!autocompleteParams) {
|
||||
var textbox = document.getAnonymousNodes(this)[0];
|
||||
textbox.removeAttribute('type');
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:textbox id="search-textbox" xbl:inherits="hasOptions,flex">
|
||||
<xul:popupset>
|
||||
<xul:menupopup id="textbox-fulltext-menu">
|
||||
<xul:menuitem type="radio" label="&zotero.search.textModes.phrase;"/>
|
||||
<xul:menuitem type="radio" label="&zotero.search.textModes.phraseBinary;"/>
|
||||
<xul:menuitem type="radio" label="&zotero.search.textModes.regexp;"/>
|
||||
<xul:menuitem type="radio" label="&zotero.search.textModes.regexpCS;"/>
|
||||
</xul:menupopup>
|
||||
</xul:popupset>
|
||||
|
||||
<xul:toolbarbutton id="textbox-button" type="menu"/>
|
||||
</xul:textbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
|
||||
<binding id="search-in-the-last">
|
||||
<resources>
|
||||
<stylesheet src="chrome://zotero/skin/bindings/search.css"/>
|
||||
</resources>
|
||||
|
||||
<implementation>
|
||||
<property name="value">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var menulist = document.getAnonymousNodes(this)[0].firstChild.nextSibling;
|
||||
|
||||
return document.getAnonymousNodes(this)[0].firstChild.value + ' ' +
|
||||
menulist.firstChild.childNodes[menulist.selectedIndex].getAttribute('value')
|
||||
]]>
|
||||
</getter>
|
||||
<setter>
|
||||
<![CDATA[
|
||||
var [num, units] = val.split(' ');
|
||||
document.getAnonymousNodes(this)[0].firstChild.setAttribute('value', num);
|
||||
|
||||
var menulist = document.getAnonymousNodes(this)[0].firstChild.nextSibling;
|
||||
var menupopup = menulist.firstChild;
|
||||
|
||||
var selectThis = 0;
|
||||
for (var i=0; i<menupopup.childNodes.length; i++){
|
||||
if (menupopup.childNodes[i].value == units)
|
||||
{
|
||||
selectThis = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
menulist.selectedIndex = selectThis;
|
||||
|
||||
return val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<method name="id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:hbox id="search-in-the-last" flex="1">
|
||||
<xul:textbox flex="1"/>
|
||||
<xul:menulist>
|
||||
<xul:menupopup flex="1">
|
||||
<xul:menuitem label="&zotero.search.date.units.days;" value="days" selected="true"/>
|
||||
<xul:menuitem label="&zotero.search.date.units.months;" value="months"/>
|
||||
<xul:menuitem label="&zotero.search.date.units.years;" value="years"/>
|
||||
</xul:menupopup>
|
||||
</xul:menulist>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
1058
chrome/content/zotero/browser.js
Normal file
73
chrome/content/zotero/captcha.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_Captcha = new function() {
|
||||
this._io;
|
||||
|
||||
this.onLoad = function() {
|
||||
this._io = window.arguments[0];
|
||||
var description = document.getElementById('zotero-captcha-description'),
|
||||
errorMsg = document.getElementById('zotero-captcha-error');
|
||||
|
||||
if(this._io.dataIn.title) {
|
||||
document.title = this._io.dataIn.title;
|
||||
}
|
||||
|
||||
if(this._io.dataIn.description) {
|
||||
description.textContent = this._io.dataIn.description;
|
||||
description.hidden = false;
|
||||
} else {
|
||||
description.hidden = true;
|
||||
}
|
||||
|
||||
if(this._io.dataIn.error) {
|
||||
errorMsg.textContent = this._io.dataIn.error;
|
||||
errorMsg.hidden = false;
|
||||
} else {
|
||||
errorMsg.hidden = true;
|
||||
}
|
||||
|
||||
document.getElementById('zotero-captcha-image').src = this._io.dataIn.imgUrl;
|
||||
document.getElementById('zotero-captcha-input').focus();
|
||||
}
|
||||
|
||||
this.imageOnLoad = function() {
|
||||
window.sizeToContent();
|
||||
}
|
||||
|
||||
this.resolve = function() {
|
||||
var result = document.getElementById('zotero-captcha-input');
|
||||
if(!result.value) return;
|
||||
|
||||
this._io.dataOut = {
|
||||
captcha: result.value
|
||||
};
|
||||
window.close();
|
||||
}
|
||||
|
||||
this.cancel = function() {
|
||||
window.close();
|
||||
}
|
||||
}
|
27
chrome/content/zotero/captcha.xul
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="Zotero_Captcha.onLoad();"
|
||||
id="zotero-captcha"
|
||||
onkeypress="if(event.keyCode === KeyEvent.DOM_VK_ESCAPE) Zotero_Captcha.cancel();">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="captcha.js"/>
|
||||
|
||||
<vbox style="padding:10px" align="center" flex="1">
|
||||
<description id="zotero-captcha-description"></description>
|
||||
<image id="zotero-captcha-image" onload="Zotero_Captcha.imageOnLoad();" />
|
||||
<description id="zotero-captcha-error"></description>
|
||||
<textbox id="zotero-captcha-input"
|
||||
onkeypress="if(event.keyCode === KeyEvent.DOM_VK_RETURN) Zotero_Captcha.resolve();" />
|
||||
<hbox>
|
||||
<button label="&zotero.general.ok;" default="true" oncommand="Zotero_Captcha.resolve();" />
|
||||
<button label="&zotero.general.cancel;" oncommand="Zotero_Captcha.cancel();" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
143
chrome/content/zotero/charsetMenu.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_Charset_Menu = new function() {
|
||||
this.populate = populate;
|
||||
|
||||
/**
|
||||
* Populate a character set menu, placing more commonly used character sets
|
||||
* closer to the top
|
||||
*
|
||||
* @param {DOMElement} charsetMenu The menu to populate
|
||||
* @param {Boolean} exportMenu Whether the menu is to be used for export
|
||||
**/
|
||||
function populate(charsetMenu, exportMenu) {
|
||||
var charsetMap = {};
|
||||
|
||||
// get charset popup and charset RDF
|
||||
var charsetPopup = document.createElement("menupopup");
|
||||
charsetMenu.appendChild(charsetPopup);
|
||||
var charsetSeparator = document.createElement("menuseparator");
|
||||
charsetPopup.appendChild(charsetSeparator);
|
||||
|
||||
var charsets = [];
|
||||
|
||||
if(Zotero.platformMajorVersion >= 32) {
|
||||
Components.utils.import("resource://gre/modules/CharsetMenu.jsm");
|
||||
var cmData = CharsetMenu.getData();
|
||||
for each(var charsetList in [cmData.pinnedCharsets, cmData.otherCharsets]) {
|
||||
for each(var charsetInfo in charsetList) {
|
||||
if(charsetInfo.value == "UTF-8") {
|
||||
charsets.push({
|
||||
"label":"Unicode (UTF-8)",
|
||||
"value":"UTF-8"
|
||||
});
|
||||
} else {
|
||||
charsets.push({
|
||||
"label":charsetInfo.label,
|
||||
"value":charsetInfo.value
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
charsets = charsets.concat([
|
||||
{"label":"UTF-16LE", "value":"UTF-16LE"},
|
||||
{"label":"UTF-16BE", "value":"UTF-16BE"},
|
||||
{"label":"Western (IBM-850)", "value":"IBM850"},
|
||||
{"label":"Western (MacRoman)", "value":"macintosh"}
|
||||
]);
|
||||
} else {
|
||||
var charsetConverter = Components.classes["@mozilla.org/charset-converter-manager;1"].
|
||||
getService(Components.interfaces.nsICharsetConverterManager);
|
||||
var ccCharsets = charsetConverter.getEncoderList();
|
||||
// add charsets to popup in order
|
||||
while(ccCharsets.hasMore()) {
|
||||
var charset = ccCharsets.getNext();
|
||||
try {
|
||||
var label = charsetConverter.getCharsetTitle(charset);
|
||||
} catch(e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var isUTF16 = charset.length >= 6 && charset.substr(0, 6) == "UTF-16";
|
||||
|
||||
// Show UTF-16 element appropriately depending on exportMenu
|
||||
if(isUTF16 && exportMenu == (charset == "UTF-16") ||
|
||||
(!exportMenu && charset == "UTF-32LE")) {
|
||||
continue;
|
||||
} else if(charset == "x-mac-roman") {
|
||||
// use the IANA name
|
||||
charset = "macintosh";
|
||||
} else if(!exportMenu && charset == "UTF-32BE") {
|
||||
label = "Unicode (UTF-32)";
|
||||
charset = "UTF-32";
|
||||
}
|
||||
charsets.push({
|
||||
"label":label,
|
||||
"value":charset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for(var i=0; i<charsets.length; i++) {
|
||||
var charset = charsets[i].value,
|
||||
label = charsets[i].label;
|
||||
|
||||
// add element
|
||||
var itemNode = document.createElement("menuitem");
|
||||
itemNode.setAttribute("label", label);
|
||||
itemNode.setAttribute("value", charset);
|
||||
|
||||
charsetMap[charset] = itemNode;
|
||||
if(isUTF16 || (label.length >= 7 &&
|
||||
label.substr(0, 7) == "Western")) {
|
||||
charsetPopup.insertBefore(itemNode, charsetSeparator);
|
||||
} else if(charset == "UTF-8") {
|
||||
var oldFirst = (charsetPopup.firstChild ? charsetPopup.firstChild : null);
|
||||
charsetPopup.insertBefore(itemNode, oldFirst);
|
||||
// also add (without BOM) if requested
|
||||
if(exportMenu) {
|
||||
var itemNode = document.createElement("menuitem");
|
||||
itemNode.setAttribute("label", Zotero.getString("charset.UTF8withoutBOM"));
|
||||
itemNode.setAttribute("value", charset+"xBOM");
|
||||
charsetMap[charset+"xBOM"] = itemNode;
|
||||
charsetPopup.insertBefore(itemNode, oldFirst);
|
||||
}
|
||||
} else {
|
||||
charsetPopup.appendChild(itemNode);
|
||||
}
|
||||
}
|
||||
|
||||
if(!exportMenu) {
|
||||
var itemNode = document.createElement("menuitem");
|
||||
itemNode.setAttribute("label", Zotero.getString("charset.autoDetect"));
|
||||
itemNode.setAttribute("value", "auto");
|
||||
charsetMap["auto"] = itemNode;
|
||||
charsetPopup.insertBefore(itemNode, charsetPopup.firstChild);
|
||||
}
|
||||
|
||||
return charsetMap;
|
||||
}
|
||||
}
|
213
chrome/content/zotero/downloadOverlay.js
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2011 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
var Zotero_DownloadOverlay = new function() {
|
||||
const PDF_MIME_TYPE = "application/pdf";
|
||||
const ALLOW_LIST = [
|
||||
"application/pdf",
|
||||
"application/postscript",
|
||||
"application/xhtml+xml",
|
||||
"text/html",
|
||||
"text/plain",
|
||||
/^audio\//,
|
||||
/^image\//,
|
||||
/^video\//,
|
||||
/^application\/vnd\.oasis\.opendocument\./,
|
||||
/^application\/vnd\.ms-/,
|
||||
/^application\/vnd\.openxmlformats-officedocument/,
|
||||
/^application\/vnd\.lotus-/,
|
||||
/^application\/vnd\.wolfram\./,
|
||||
"application/vnd.wordperfect",
|
||||
"application/wordperfect5.1",
|
||||
"application/msword",
|
||||
"application/x-latex"
|
||||
];
|
||||
|
||||
/**
|
||||
* Saves this item, if we are supposed to save it.
|
||||
*
|
||||
* @return {Boolean} True if an item was saved, false if we were not supposed to save
|
||||
*/
|
||||
this.handleSave = function() {
|
||||
if(!document.getElementById('zotero-radio').selected) return false;
|
||||
|
||||
var retrieveMetadata = document.getElementById('zotero-recognizePDF').selected;
|
||||
|
||||
var url = dialog.mLauncher.source.spec;
|
||||
Zotero.debug("Zotero_DownloadOverlay: Downloading from "+url);
|
||||
|
||||
// set up progress window
|
||||
var win = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator)
|
||||
.getMostRecentWindow("navigator:browser");
|
||||
var libraryID, collection;
|
||||
try {
|
||||
let itemGroup = win.ZoteroPane.getItemGroup();
|
||||
if (itemGroup.filesEditable) {
|
||||
libraryID = win.ZoteroPane.getSelectedLibraryID();
|
||||
collection = win.ZoteroPane.getSelectedCollection();
|
||||
}
|
||||
// TODO: Just show an error instead?
|
||||
else {
|
||||
Zotero.debug("Cannot save files to library " + itemGroup.ref.libraryID
|
||||
+ " -- saving to personal library instead", 2);
|
||||
}
|
||||
} catch(e) {
|
||||
Zotero.debug(e, 1);
|
||||
};
|
||||
|
||||
var recognizePDF = document.getElementById('zotero-recognizePDF').checked
|
||||
&& !document.getElementById('zotero-recognizePDF').hidden
|
||||
&& !document.getElementById('zotero-recognizePDF').disabled;
|
||||
|
||||
// set up callback
|
||||
var callback = function(item) {
|
||||
if(!win) return;
|
||||
|
||||
if(item) {
|
||||
progressWin.addLines([item.getDisplayTitle()], [item.getImageSrc()]);
|
||||
progressWin.startCloseTimer();
|
||||
if(collection) collection.addItem(item.id);
|
||||
} else {
|
||||
progressWin.addDescription(Zotero.getString("save.link.error"));
|
||||
progressWin.startCloseTimer(8000);
|
||||
}
|
||||
|
||||
if(recognizePDF) {
|
||||
var timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(Components.interfaces.nsITimer);
|
||||
timer.init(function() {
|
||||
try {
|
||||
if(item.getFile()) {
|
||||
timer.cancel();
|
||||
var recognizer = new win.Zotero_RecognizePDF.ItemRecognizer();
|
||||
recognizer.recognizeItems([item]);
|
||||
}
|
||||
} catch(e) { dump(e.toSource()) };
|
||||
}, 1000, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
|
||||
}
|
||||
};
|
||||
|
||||
// show progress dialog
|
||||
var progressWin = new Zotero.ProgressWindow();
|
||||
progressWin.changeHeadline(Zotero.getString("save.link"));
|
||||
progressWin.show();
|
||||
|
||||
// perform import
|
||||
Zotero.Attachments.importFromURL(url, false, false, false,
|
||||
collection ? [collection.id] : [], dialog.mLauncher.MIMEInfo.MIMEType,
|
||||
libraryID, callback);
|
||||
|
||||
// mimic dialog cancellation
|
||||
dialog.onCancel();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when mode in dialog has been changed
|
||||
*/
|
||||
this.modeChanged = function() {
|
||||
var zoteroSelected = document.getElementById('zotero-radio').selected;
|
||||
|
||||
// don't allow user to remember Zotero option for file type; i'm not sure anyone wants this
|
||||
// to happen automatically
|
||||
if(zoteroSelected) document.getElementById('rememberChoice').selected = false;
|
||||
document.getElementById('rememberChoice').disabled = zoteroSelected;
|
||||
|
||||
// disable recognizePDF checkbox as necessary
|
||||
if(!Zotero.Fulltext.pdfConverterIsRegistered()) {
|
||||
document.getElementById('zotero-noPDFTools-description').hidden = !zoteroSelected;
|
||||
document.getElementById('zotero-recognizePDF').disabled = true;
|
||||
window.sizeToContent();
|
||||
} else {
|
||||
document.getElementById('zotero-recognizePDF').disabled = !zoteroSelected;
|
||||
}
|
||||
|
||||
Zotero_DownloadOverlay.updateLibraryNote();
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the note stating that the item will be saved to "My Library" is shown
|
||||
*/
|
||||
this.updateLibraryNote = function() {
|
||||
var zoteroSelected = document.getElementById('zotero-radio').selected;
|
||||
var zp = Zotero.getActiveZoteroPane(), canSave = true;
|
||||
try {
|
||||
canSave = zp.getItemGroup().filesEditable;
|
||||
} catch(e) {
|
||||
Zotero.logError(e);
|
||||
};
|
||||
document.getElementById('zotero-saveToLibrary-description').hidden = !zoteroSelected || canSave;
|
||||
window.sizeToContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the save dialog is opened
|
||||
*/
|
||||
this.init = function() {
|
||||
if(Zotero.isConnector) return;
|
||||
|
||||
// Disable for filetypes people probably don't want to save
|
||||
var show = false;
|
||||
var mimeType = dialog.mLauncher.MIMEInfo.MIMEType.toLowerCase();
|
||||
for each(var elem in ALLOW_LIST) {
|
||||
if(typeof elem === "string") {
|
||||
if(elem === mimeType) {
|
||||
document.getElementById('zotero-container').hidden = false;
|
||||
document.getElementById('zotero-radio').disabled = false;
|
||||
break;
|
||||
}
|
||||
} else if(elem.test(mimeType)) {
|
||||
document.getElementById('zotero-container').hidden = false;
|
||||
document.getElementById('zotero-radio').disabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Hook in event listener to ondialogaccept
|
||||
document.documentElement.setAttribute('ondialogaccept',
|
||||
'if(!Zotero_DownloadOverlay.handleSave()) { '
|
||||
+ document.documentElement.getAttribute('ondialogaccept')
|
||||
+'}');
|
||||
|
||||
// Hook in event listener for mode change
|
||||
var radios = document.getElementById('mode').
|
||||
addEventListener("command", Zotero_DownloadOverlay.modeChanged, false);
|
||||
|
||||
// Set label on retrieve PDF option
|
||||
if(mimeType === PDF_MIME_TYPE) {
|
||||
var recognizePDF = document.getElementById('zotero-recognizePDF');
|
||||
recognizePDF.label = Zotero.getString("pane.items.menu.recognizePDF");
|
||||
recognizePDF.hidden = false;
|
||||
recognizePDF.disabled = true;
|
||||
if(!Zotero.Fulltext.pdfConverterIsRegistered()) {
|
||||
recognizePDF.checked = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
window.addEventListener("load", Zotero_DownloadOverlay.init, false);
|
||||
window.addEventListener("activate", Zotero_DownloadOverlay.updateLibraryNote, false);
|
51
chrome/content/zotero/downloadOverlay.xul
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2011 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on code derived from FlashGot - a Firefox extension for external
|
||||
download managers integration.
|
||||
Copyright (C) 2004-2011 Giorgio Maone - g.maone@informaction.com
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd"> %zoteroDTD;
|
||||
]>
|
||||
|
||||
<overlay id="zotero-download-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/x-javascript" src="include.js"/>
|
||||
<script type="application/x-javascript" src="downloadOverlay.js"/>
|
||||
<radiogroup id="mode">
|
||||
<vbox id="zotero-container" flex="1" hidden="true">
|
||||
<radio id="zotero-radio" label="&zotero.downloadManager.label;" disabled="true"/>
|
||||
<vbox style="margin-left: 15px">
|
||||
<description id="zotero-saveToLibrary-description" style="font: small-caption; font-weight: normal" hidden="true">&zotero.downloadManager.saveToLibrary.description;</description>
|
||||
<checkbox id="zotero-recognizePDF" hidden="true" persist="checked" disabled="true"/>
|
||||
<description style="margin-left: 20px; font: small-caption; font-weight: normal" id="zotero-noPDFTools-description" hidden="true">&zotero.downloadManager.noPDFTools.description;</description>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</radiogroup>
|
||||
</overlay>
|
||||
|
151
chrome/content/zotero/duplicatesMerge.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_Duplicates_Pane = new function () {
|
||||
_items = [];
|
||||
_otherItems = [];
|
||||
_ignoreFields = ['dateAdded', 'dateModified', 'accessDate'];
|
||||
|
||||
this.setItems = function (items, displayNumItemsOnTypeError) {
|
||||
var itemTypeID, oldestItem, otherItems = [];
|
||||
for each(var item in items) {
|
||||
// Find the oldest item
|
||||
if (!oldestItem) {
|
||||
oldestItem = item;
|
||||
}
|
||||
else if (item.dateAdded < oldestItem.dateAdded) {
|
||||
otherItems.push(oldestItem);
|
||||
oldestItem = item;
|
||||
}
|
||||
else {
|
||||
otherItems.push(item);
|
||||
}
|
||||
|
||||
if (!item.isRegularItem() || [1,14].indexOf(item.itemTypeID) != -1) {
|
||||
var msg = Zotero.getString('pane.item.duplicates.onlyTopLevel');
|
||||
ZoteroPane_Local.setItemPaneMessage(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure all items are of the same type
|
||||
if (itemTypeID) {
|
||||
if (itemTypeID != item.itemTypeID) {
|
||||
if (displayNumItemsOnTypeError) {
|
||||
var msg = Zotero.getString('pane.item.selected.multiple', items.length);
|
||||
}
|
||||
else {
|
||||
var msg = Zotero.getString('pane.item.duplicates.onlySameItemType');
|
||||
}
|
||||
ZoteroPane_Local.setItemPaneMessage(msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
itemTypeID = item.itemTypeID;
|
||||
}
|
||||
}
|
||||
|
||||
_items = items;
|
||||
|
||||
_items.sort(function (a, b) {
|
||||
return a.dateAdded > b.dateAdded ? 1 : a.dateAdded == b.dateAdded ? 0 : -1;
|
||||
});
|
||||
|
||||
//
|
||||
// Update the UI
|
||||
//
|
||||
|
||||
var diff = oldestItem.multiDiff(otherItems, _ignoreFields);
|
||||
|
||||
var button = document.getElementById('zotero-duplicates-merge-button');
|
||||
var versionSelect = document.getElementById('zotero-duplicates-merge-version-select');
|
||||
var itembox = document.getElementById('zotero-duplicates-merge-item-box');
|
||||
var fieldSelect = document.getElementById('zotero-duplicates-merge-field-select');
|
||||
|
||||
versionSelect.hidden = !diff;
|
||||
if (diff) {
|
||||
// Populate menulist with Date Added values from all items
|
||||
var dateList = document.getElementById('zotero-duplicates-merge-original-date');
|
||||
|
||||
while (dateList.itemCount) {
|
||||
dateList.removeItemAt(0);
|
||||
}
|
||||
|
||||
var numRows = 0;
|
||||
for each(var item in _items) {
|
||||
var date = Zotero.Date.sqlToDate(item.dateAdded, true);
|
||||
dateList.appendItem(date.toLocaleString());
|
||||
numRows++;
|
||||
}
|
||||
|
||||
dateList.setAttribute('rows', numRows);
|
||||
|
||||
// If we set this inline, the selection doesn't take on the first
|
||||
// selection after unhiding versionSelect (when clicking
|
||||
// from a set with no differences) -- tested in Fx5.0.1
|
||||
setTimeout(function () {
|
||||
dateList.selectedIndex = 0;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
button.label = Zotero.getString('pane.item.duplicates.mergeItems', (otherItems.length + 1));
|
||||
itembox.hiddenFields = diff ? [] : ['dateAdded', 'dateModified'];
|
||||
fieldSelect.hidden = !diff;
|
||||
|
||||
this.setMaster(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
this.setMaster = function (pos) {
|
||||
var itembox = document.getElementById('zotero-duplicates-merge-item-box');
|
||||
itembox.mode = 'fieldmerge';
|
||||
|
||||
_otherItems = _items.concat();
|
||||
var item = _otherItems.splice(pos, 1)[0];
|
||||
|
||||
// Add master item's values to the beginning of each set of
|
||||
// alternative values so that they're still available if the item box
|
||||
// modifies the item
|
||||
var diff = item.multiDiff(_otherItems, _ignoreFields);
|
||||
if (diff) {
|
||||
var itemValues = item.serialize()
|
||||
for (var i in diff) {
|
||||
diff[i].unshift(itemValues.fields[i]);
|
||||
}
|
||||
itembox.fieldAlternatives = diff;
|
||||
}
|
||||
|
||||
itembox.item = item.clone(true);
|
||||
}
|
||||
|
||||
|
||||
this.merge = function () {
|
||||
var itembox = document.getElementById('zotero-duplicates-merge-item-box');
|
||||
Zotero.ItemGroupCache.clear();
|
||||
Zotero.Items.merge(itembox.item, _otherItems);
|
||||
}
|
||||
}
|
168
chrome/content/zotero/errorReport.xul
Normal file
|
@ -0,0 +1,168 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/errorReport.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="zotero-error-report" title="&zotero.errorReport.title;"
|
||||
width="550" height="450">
|
||||
|
||||
<script>
|
||||
<![CDATA[
|
||||
Components.utils.import("resource://zotero/config.js");
|
||||
|
||||
var Zotero_Error_Report = new function() {
|
||||
this.init = init;
|
||||
this.sendErrorReport = sendErrorReport;
|
||||
|
||||
var obj = window.arguments[0].wrappedJSObject;
|
||||
var Zotero = obj.Zotero;
|
||||
var data = obj.data;
|
||||
var msg = data.msg;
|
||||
var errorData = data.errorData;
|
||||
var extraData = data.extraData ? data.extraData : '';
|
||||
var diagnosticInfo = false;
|
||||
|
||||
|
||||
function init() {
|
||||
var wizard = document.getElementById('zotero-error-report');
|
||||
var continueButton = wizard.getButton('next');
|
||||
continueButton.disabled = true;
|
||||
|
||||
Zotero.getSystemInfo(function(info) {
|
||||
var errorDataText = errorData.length
|
||||
? data.errorData.join('\n')
|
||||
: Zotero.getString('errorReport.noErrorsLogged', Zotero.appName);
|
||||
|
||||
diagnosticInfo = info;
|
||||
|
||||
var logText = errorDataText + '\n\n'
|
||||
+ (extraData !== '' ? extraData + '\n\n' : '')
|
||||
+ diagnosticInfo;
|
||||
|
||||
if (document.getElementById('zotero-failure-message').hasChildNodes()) {
|
||||
var textNode = document.getElementById('zotero-failure-message').firstChild;
|
||||
document.getElementById('zotero-failure-message').removeChild(textNode);
|
||||
}
|
||||
|
||||
document.getElementById('zotero-failure-message').appendChild(document.createTextNode(msg));
|
||||
document.getElementById('zotero-error-message').value = logText;
|
||||
|
||||
continueButton.disabled = false;
|
||||
continueButton.focus();
|
||||
var str = Zotero.getString(
|
||||
'errorReport.advanceMessage', continueButton.getAttribute('label')
|
||||
);
|
||||
document.getElementById('zotero-advance-message').setAttribute('value', str);
|
||||
});
|
||||
}
|
||||
|
||||
function sendErrorReport() {
|
||||
var wizard = document.getElementById('zotero-error-report');
|
||||
var continueButton = wizard.getButton('next');
|
||||
continueButton.disabled = true;
|
||||
|
||||
var parts = {
|
||||
error: "true",
|
||||
errorData: errorData.join('\n'),
|
||||
extraData: extraData,
|
||||
diagnostic: diagnosticInfo
|
||||
};
|
||||
|
||||
var body = '';
|
||||
for (var key in parts) {
|
||||
body += key + '=' + encodeURIComponent(parts[key]) + '&';
|
||||
}
|
||||
body = body.substr(0, body.length - 1);
|
||||
var url = ZOTERO_CONFIG.REPOSITORY_URL + "report";
|
||||
Zotero.HTTP.promise('POST', url,
|
||||
{ body: body, successCodes: false, foreground: true })
|
||||
.then(_sendErrorReportCallback)
|
||||
.done();
|
||||
}
|
||||
|
||||
|
||||
function _sendErrorReportCallback(xmlhttp) {
|
||||
var wizard = document.getElementById('zotero-error-report');
|
||||
if (!wizard) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
if (!xmlhttp.responseXML){
|
||||
try {
|
||||
if (xmlhttp.status>1000){
|
||||
ps.alert(
|
||||
null,
|
||||
Zotero.getString('general.error'),
|
||||
Zotero.getString('errorReport.noNetworkConnection')
|
||||
);
|
||||
}
|
||||
else {
|
||||
ps.alert(
|
||||
null,
|
||||
Zotero.getString('general.error'),
|
||||
Zotero.getString('errorReport.invalidResponseRepository')
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (e){
|
||||
ps.alert(
|
||||
null,
|
||||
Zotero.getString('general.error'),
|
||||
Zotero.getString('errorReport.repoCannotBeContacted')
|
||||
);
|
||||
}
|
||||
|
||||
wizard.rewind();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
|
||||
if (reported.length != 1) {
|
||||
ps.alert(
|
||||
null,
|
||||
Zotero.getString('general.error'),
|
||||
Zotero.getString('errorReport.invalidResponseRepository')
|
||||
);
|
||||
wizard.rewind();
|
||||
return;
|
||||
}
|
||||
|
||||
wizard.advance();
|
||||
wizard.getButton('cancel').disabled = true;;
|
||||
wizard.canRewind = false;
|
||||
var reportID = reported[0].getAttribute('reportID');
|
||||
document.getElementById('zotero-report-id').setAttribute('value', reportID);
|
||||
document.getElementById('zotero-report-result').hidden = false;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<wizardpage onpageshow="Zotero_Error_Report.init()" label=" ">
|
||||
<description id="zotero-failure-message"/>
|
||||
<textbox id="zotero-error-message" class="plain" readonly="true" multiline="true" flex="1"/>
|
||||
<description id="zotero-unrelated-message">&zotero.general.note; &zotero.errorReport.unrelatedMessages;</description>
|
||||
<description id="zotero-advance-message"/>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage onpageshow="Zotero_Error_Report.sendErrorReport()" label=" ">
|
||||
<description>&zotero.errorReport.submissionInProgress;</description>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage label=" ">
|
||||
<description>&zotero.errorReport.submitted;</description>
|
||||
<description id="zotero-report-result" hidden="true">
|
||||
&zotero.errorReport.reportID;
|
||||
<textbox id="zotero-report-id" class="plain" readonly="true"/>
|
||||
</description>
|
||||
<description>&zotero.errorReport.postToForums;</description>
|
||||
<description>&zotero.errorReport.notReviewed;</description>
|
||||
</wizardpage>
|
||||
</wizard>
|
224
chrome/content/zotero/exportOptions.js
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zotero_File_Interface_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const OPTION_PREFIX = "export-option-";
|
||||
|
||||
// Class to provide options for export
|
||||
|
||||
var Zotero_File_Interface_Export = new function() {
|
||||
this.init = init;
|
||||
this.updateOptions = updateOptions;
|
||||
this.accept = accept;
|
||||
this.cancel = cancel;
|
||||
|
||||
var _charsets = false;
|
||||
|
||||
/*
|
||||
* add options to export
|
||||
*/
|
||||
function init() {
|
||||
// Set font size from pref
|
||||
var sbc = document.getElementById('zotero-export-options-container');
|
||||
Zotero.setFontSize(sbc);
|
||||
|
||||
var addedOptions = new Object();
|
||||
|
||||
var translators = window.arguments[0].translators;
|
||||
translators.sort(function(a, b) { return a.label.localeCompare(b.label) });
|
||||
|
||||
// get format popup
|
||||
var formatPopup = document.getElementById("format-popup");
|
||||
var formatMenu = document.getElementById("format-menu");
|
||||
var optionsBox = document.getElementById("translator-options");
|
||||
var charsetBox = document.getElementById("charset-box");
|
||||
|
||||
var selectedTranslator = Zotero.Prefs.get("export.lastTranslator");
|
||||
|
||||
// add styles to format popup
|
||||
for(var i in translators) {
|
||||
var itemNode = document.createElement("menuitem");
|
||||
itemNode.setAttribute("label", translators[i].label);
|
||||
formatPopup.appendChild(itemNode);
|
||||
|
||||
// add options
|
||||
for(var option in translators[i].displayOptions) {
|
||||
if(!addedOptions[option]) { // if this option is not already
|
||||
// presented to the user
|
||||
// get readable name for option
|
||||
try {
|
||||
var optionLabel = Zotero.getString("exportOptions."+option);
|
||||
} catch(e) {
|
||||
var optionLabel = option;
|
||||
}
|
||||
|
||||
// right now, option interface supports only boolean values, which
|
||||
// it interprets as checkboxes
|
||||
if(typeof(translators[i].displayOptions[option]) == "boolean") {
|
||||
var checkbox = document.createElement("checkbox");
|
||||
checkbox.setAttribute("id", OPTION_PREFIX+option);
|
||||
checkbox.setAttribute("label", optionLabel);
|
||||
optionsBox.insertBefore(checkbox, charsetBox);
|
||||
}
|
||||
|
||||
addedOptions[option] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// select last selected translator
|
||||
if(translators[i].translatorID == selectedTranslator) {
|
||||
formatMenu.selectedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// select first item by default
|
||||
if(formatMenu.selectedIndex == -1) {
|
||||
formatMenu.selectedIndex = 0;
|
||||
}
|
||||
|
||||
// from charsetMenu.js
|
||||
if(Zotero.Prefs.get("export.displayCharsetOption")) {
|
||||
_charsets = Zotero_Charset_Menu.populate(document.getElementById(OPTION_PREFIX+"exportCharset"), true);
|
||||
}
|
||||
|
||||
updateOptions(Zotero.Prefs.get("export.translatorSettings"));
|
||||
}
|
||||
|
||||
/*
|
||||
* update translator-specific options
|
||||
*/
|
||||
function updateOptions(optionString) {
|
||||
// get selected translator
|
||||
var index = document.getElementById("format-menu").selectedIndex;
|
||||
var translatorOptions = window.arguments[0].translators[index].displayOptions;
|
||||
|
||||
if(optionString) {
|
||||
try {
|
||||
var options = JSON.parse(optionString);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
var optionsBox = document.getElementById("translator-options");
|
||||
optionsBox.hidden = true;
|
||||
var haveOption = false;
|
||||
for(var i=0; i<optionsBox.childNodes.length; i++) {
|
||||
// loop through options to see which should be enabled
|
||||
var node = optionsBox.childNodes[i];
|
||||
// skip non-options
|
||||
if(node.id.length <= OPTION_PREFIX.length
|
||||
|| node.id.substr(0, OPTION_PREFIX.length) != OPTION_PREFIX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var optionName = node.id.substr(OPTION_PREFIX.length);
|
||||
if(translatorOptions[optionName] != undefined) {
|
||||
// option should be enabled
|
||||
optionsBox.hidden = undefined;
|
||||
node.hidden = undefined;
|
||||
|
||||
var defValue = translatorOptions[optionName];
|
||||
if(typeof(defValue) == "boolean") {
|
||||
if(options && options[optionName] !== undefined) {
|
||||
// if there's a saved prefs string, use it
|
||||
var isChecked = options[optionName];
|
||||
} else {
|
||||
// use defaults
|
||||
var isChecked = (defValue ? "true" : "false");
|
||||
}
|
||||
node.setAttribute("checked", isChecked);
|
||||
}
|
||||
} else {
|
||||
// option should be disabled and unchecked to prevent confusion
|
||||
node.hidden = true;
|
||||
node.checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
// handle charset popup
|
||||
if(_charsets && translatorOptions.exportCharset) {
|
||||
optionsBox.hidden = undefined;
|
||||
document.getElementById("charset-box").hidden = undefined;
|
||||
var charsetMenu = document.getElementById(OPTION_PREFIX+"exportCharset");
|
||||
var charset = "UTF-8";
|
||||
if(options && options.exportCharset && _charsets[options.exportCharset]) {
|
||||
charset = options.exportCharset;
|
||||
} else if(translatorOptions.exportCharset && _charsets[translatorOptions.exportCharset]) {
|
||||
charset = translatorOptions.exportCharset;
|
||||
}
|
||||
|
||||
charsetMenu.selectedItem = _charsets[charset];
|
||||
} else {
|
||||
document.getElementById("charset-box").hidden = true;
|
||||
}
|
||||
|
||||
window.sizeToContent();
|
||||
}
|
||||
|
||||
/*
|
||||
* make option array reflect status
|
||||
*/
|
||||
function accept() {
|
||||
// set selected translator
|
||||
var index = document.getElementById("format-menu").selectedIndex;
|
||||
window.arguments[0].selectedTranslator = window.arguments[0].translators[index];
|
||||
|
||||
// save selected translator
|
||||
Zotero.Prefs.set("export.lastTranslator", window.arguments[0].translators[index].translatorID);
|
||||
|
||||
// set options on selected translator and generate optionString
|
||||
var optionsAvailable = window.arguments[0].selectedTranslator.displayOptions;
|
||||
var displayOptions = window.arguments[0].displayOptions = {};
|
||||
for(var option in optionsAvailable) {
|
||||
var defValue = optionsAvailable[option];
|
||||
var element = document.getElementById(OPTION_PREFIX+option);
|
||||
|
||||
if(option == "exportCharset") {
|
||||
if(_charsets) {
|
||||
displayOptions[option] = element.selectedItem.value;
|
||||
} else {
|
||||
displayOptions[option] = optionsAvailable[option];
|
||||
}
|
||||
} else if(typeof(defValue) == "boolean") {
|
||||
displayOptions[option] = !!element.checked;
|
||||
}
|
||||
}
|
||||
|
||||
// save options
|
||||
var optionString = JSON.stringify(displayOptions);
|
||||
Zotero.Prefs.set("export.translatorSettings", optionString);
|
||||
}
|
||||
|
||||
/*
|
||||
* make option array reflect status
|
||||
*/
|
||||
function cancel() {
|
||||
window.arguments[0].selectedTranslator = false;
|
||||
}
|
||||
}
|
43
chrome/content/zotero/exportOptions.xul
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd" >
|
||||
%zoteroDTD;
|
||||
]>
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
title="&zotero.exportOptions.title;" buttons="cancel,accept"
|
||||
ondialogaccept="Zotero_File_Interface_Export.accept()"
|
||||
ondialogcancel="Zotero_File_Interface_Export.cancel()"
|
||||
id="zotero-export-options"
|
||||
onload="Zotero_File_Interface_Export.init()">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="charsetMenu.js"/>
|
||||
<script src="exportOptions.js"/>
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
|
||||
observerService.notifyObservers(null, "charsetmenu-selected", "other");
|
||||
]]>
|
||||
</script>
|
||||
|
||||
|
||||
<vbox id="zotero-export-options-container" flex="1">
|
||||
<hbox>
|
||||
<label value="&zotero.exportOptions.format.label;" control="format-menu"/>
|
||||
<menulist id="format-menu" oncommand="Zotero_File_Interface_Export.updateOptions()">
|
||||
<menupopup id="format-popup"/>
|
||||
</menulist>
|
||||
</hbox>
|
||||
<groupbox id="translator-options">
|
||||
<caption id="translator-options-label" label="&zotero.exportOptions.translatorOptions.label;"/>
|
||||
|
||||
<vbox id="charset-box" hidden="true">
|
||||
<separator class="thin"/>
|
||||
<label value="&zotero.charset.label;:" control="charset-menu"/>
|
||||
<menulist id="export-option-exportCharset"/>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</dialog>
|
683
chrome/content/zotero/fileInterface.js
Normal file
|
@ -0,0 +1,683 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/****Zotero_File_Exporter****
|
||||
**
|
||||
* A class to handle exporting of items, collections, or the entire library
|
||||
**/
|
||||
|
||||
/**
|
||||
* Constructs a new Zotero_File_Exporter with defaults
|
||||
**/
|
||||
var Zotero_File_Exporter = function() {
|
||||
this.name = Zotero.getString("fileInterface.exportedItems");
|
||||
this.collection = false;
|
||||
this.items = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual export operation
|
||||
**/
|
||||
Zotero_File_Exporter.prototype.save = function() {
|
||||
var translation = new Zotero.Translate.Export();
|
||||
var translators = translation.getTranslators();
|
||||
|
||||
// present options dialog
|
||||
var io = {translators:translators}
|
||||
window.openDialog("chrome://zotero/content/exportOptions.xul",
|
||||
"_blank", "chrome,modal,centerscreen,resizable=no", io);
|
||||
if(!io.selectedTranslator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
||||
.createInstance(nsIFilePicker);
|
||||
fp.init(window, Zotero.getString("fileInterface.export"), nsIFilePicker.modeSave);
|
||||
|
||||
// set file name and extension
|
||||
if(io.displayOptions.exportFileData) {
|
||||
// if the result will be a folder, don't append any extension or use
|
||||
// filters
|
||||
fp.defaultString = this.name;
|
||||
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
|
||||
} else {
|
||||
// if the result will be a file, append an extension and use filters
|
||||
fp.defaultString = this.name+(io.selectedTranslator.target ? "."+io.selectedTranslator.target : "");
|
||||
fp.defaultExtension = io.selectedTranslator.target;
|
||||
fp.appendFilter(io.selectedTranslator.label, "*."+(io.selectedTranslator.target ? io.selectedTranslator.target : "*"));
|
||||
}
|
||||
|
||||
var rv = fp.show();
|
||||
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
|
||||
if(this.collection) {
|
||||
translation.setCollection(this.collection);
|
||||
} else if(this.items) {
|
||||
translation.setItems(this.items);
|
||||
} else if(this.libraryID === undefined) {
|
||||
throw new Error('No export configured');
|
||||
} else {
|
||||
translation.setLibraryID(this.libraryID);
|
||||
}
|
||||
|
||||
translation.setLocation(fp.file);
|
||||
translation.setTranslator(io.selectedTranslator);
|
||||
translation.setDisplayOptions(io.displayOptions);
|
||||
translation.setHandler("itemDone", function () {
|
||||
Zotero_File_Interface.updateProgress(translation, false);
|
||||
});
|
||||
translation.setHandler("done", this._exportDone);
|
||||
Zotero.UnresponsiveScriptIndicator.disable();
|
||||
Zotero_File_Interface.Progress.show(
|
||||
Zotero.getString("fileInterface.itemsExported")
|
||||
);
|
||||
translation.translate()
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the items exported indicator
|
||||
*/
|
||||
Zotero_File_Exporter.prototype._exportDone = function(obj, worked) {
|
||||
Zotero_File_Interface.Progress.close();
|
||||
Zotero.UnresponsiveScriptIndicator.enable();
|
||||
|
||||
if(!worked) {
|
||||
window.alert(Zotero.getString("fileInterface.exportError"));
|
||||
}
|
||||
}
|
||||
|
||||
/****Zotero_File_Interface****
|
||||
**
|
||||
* A singleton to interface with ZoteroPane to provide export/bibliography
|
||||
* capabilities
|
||||
**/
|
||||
var Zotero_File_Interface = new function() {
|
||||
var _unlock;
|
||||
|
||||
this.exportFile = exportFile;
|
||||
this.exportCollection = exportCollection;
|
||||
this.exportItemsToClipboard = exportItemsToClipboard;
|
||||
this.exportItems = exportItems;
|
||||
this.importFile = importFile;
|
||||
this.bibliographyFromCollection = bibliographyFromCollection;
|
||||
this.bibliographyFromItems = bibliographyFromItems;
|
||||
this.copyItemsToClipboard = copyItemsToClipboard;
|
||||
this.copyCitationToClipboard = copyCitationToClipboard;
|
||||
|
||||
/*
|
||||
* Creates Zotero.Translate instance and shows file picker for file export
|
||||
*/
|
||||
function exportFile() {
|
||||
var exporter = new Zotero_File_Exporter();
|
||||
exporter.libraryID = ZoteroPane_Local.getSelectedLibraryID();
|
||||
if (exporter.libraryID === false) {
|
||||
throw new Error('No library selected');
|
||||
}
|
||||
exporter.name = Zotero.Libraries.getName(exporter.libraryID);
|
||||
exporter.save();
|
||||
}
|
||||
|
||||
/*
|
||||
* exports a collection or saved search
|
||||
*/
|
||||
function exportCollection() {
|
||||
var exporter = new Zotero_File_Exporter();
|
||||
|
||||
var collection = ZoteroPane_Local.getSelectedCollection();
|
||||
if(collection) {
|
||||
exporter.name = collection.getName();
|
||||
exporter.collection = collection;
|
||||
} else {
|
||||
// find sorted items
|
||||
exporter.items = ZoteroPane_Local.getSortedItems();
|
||||
if(!exporter.items) throw ("No items to save");
|
||||
|
||||
// find name
|
||||
var search = ZoteroPane_Local.getSelectedSavedSearch();
|
||||
if(search) {
|
||||
exporter.name = search.name;
|
||||
}
|
||||
}
|
||||
exporter.save();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* exports items
|
||||
*/
|
||||
function exportItems() {
|
||||
var exporter = new Zotero_File_Exporter();
|
||||
|
||||
exporter.items = ZoteroPane_Local.getSelectedItems();
|
||||
if(!exporter.items || !exporter.items.length) throw("no items currently selected");
|
||||
|
||||
exporter.save();
|
||||
}
|
||||
|
||||
/*
|
||||
* exports items to clipboard
|
||||
*/
|
||||
function exportItemsToClipboard(items, translatorID) {
|
||||
var translation = new Zotero.Translate.Export();
|
||||
translation.setItems(items);
|
||||
translation.setTranslator(translatorID);
|
||||
translation.setHandler("done", _copyToClipboard);
|
||||
translation.translate();
|
||||
}
|
||||
|
||||
/*
|
||||
* handler when done exporting items to clipboard
|
||||
*/
|
||||
function _copyToClipboard(obj, worked) {
|
||||
if(!worked) {
|
||||
window.alert(Zotero.getString("fileInterface.exportError"));
|
||||
} else {
|
||||
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Components.interfaces.nsIClipboardHelper)
|
||||
.copyString(obj.string.replace(/\r\n/g, "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Zotero.Translate instance and shows file picker for file import
|
||||
*/
|
||||
function importFile(file, createNewCollection) {
|
||||
if(createNewCollection === undefined) {
|
||||
createNewCollection = true;
|
||||
} else if(!createNewCollection) {
|
||||
try {
|
||||
if (!ZoteroPane.collectionsView.editable) {
|
||||
ZoteroPane.collectionsView.selectLibrary(null);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
var translation = new Zotero.Translate.Import();
|
||||
if(!file) {
|
||||
var translators = translation.getTranslators();
|
||||
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
||||
.createInstance(nsIFilePicker);
|
||||
fp.init(window, Zotero.getString("fileInterface.import"), nsIFilePicker.modeOpen);
|
||||
|
||||
fp.appendFilters(nsIFilePicker.filterAll);
|
||||
for(var i in translators) {
|
||||
fp.appendFilter(translators[i].label, "*."+translators[i].target);
|
||||
}
|
||||
|
||||
var rv = fp.show();
|
||||
if (rv !== nsIFilePicker.returnOK && rv !== nsIFilePicker.returnReplace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file = fp.file;
|
||||
}
|
||||
|
||||
translation.setLocation(file);
|
||||
// get translators again, bc now we can check against the file
|
||||
translation.setHandler("translators", function(obj, item) {
|
||||
_importTranslatorsAvailable(obj, item, createNewCollection);
|
||||
});
|
||||
translators = translation.getTranslators();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Imports from clipboard
|
||||
*/
|
||||
this.importFromClipboard = function () {
|
||||
var str = Zotero.Utilities.Internal.getClipboard("text/unicode");
|
||||
if(!str) {
|
||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
ps.alert(null, "", Zotero.getString('fileInterface.importClipboardNoDataError'));
|
||||
}
|
||||
|
||||
var translate = new Zotero.Translate.Import();
|
||||
translate.setString(str);
|
||||
|
||||
try {
|
||||
if (!ZoteroPane.collectionsView.editable) {
|
||||
ZoteroPane.collectionsView.selectLibrary(null);
|
||||
}
|
||||
} catch(e) {}
|
||||
translate.setHandler("translators", function(obj, item) {
|
||||
_importTranslatorsAvailable(obj, item, false);
|
||||
});
|
||||
translators = translate.getTranslators();
|
||||
}
|
||||
|
||||
|
||||
function _importTranslatorsAvailable(translation, translators, createNewCollection) {
|
||||
if(translators.length) {
|
||||
var importCollection = null, libraryID = null;
|
||||
|
||||
if(translation.location instanceof Components.interfaces.nsIFile) {
|
||||
var leafName = translation.location.leafName;
|
||||
var collectionName = (translation.location.isDirectory() || leafName.indexOf(".") === -1 ? leafName
|
||||
: leafName.substr(0, leafName.lastIndexOf(".")));
|
||||
var allCollections = Zotero.getCollections();
|
||||
for(var i=0; i<allCollections.length; i++) {
|
||||
if(allCollections[i].name == collectionName) {
|
||||
collectionName += " "+(new Date()).toLocaleString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var collectionName = Zotero.getString("fileInterface.imported")+" "+(new Date()).toLocaleString();
|
||||
}
|
||||
|
||||
if(createNewCollection) {
|
||||
// Create a new collection to take imported items
|
||||
importCollection = Zotero.Collections.add(collectionName);
|
||||
} else {
|
||||
// Import into currently selected collection
|
||||
try {
|
||||
libraryID = ZoteroPane.getSelectedLibraryID();
|
||||
importCollection = ZoteroPane.getSelectedCollection();
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
// import items
|
||||
translation.setTranslator(translators[0]);
|
||||
|
||||
if(importCollection) {
|
||||
/*
|
||||
* Saves collections after they've been imported. Input item is of the
|
||||
* type outputted by Zotero.Collection.toArray(); only receives top-level
|
||||
* collections
|
||||
*/
|
||||
translation.setHandler("collectionDone", function(obj, collection) {
|
||||
collection.parent = importCollection.id;
|
||||
collection.save();
|
||||
});
|
||||
}
|
||||
|
||||
translation.setHandler("itemDone", function () {
|
||||
Zotero_File_Interface.updateProgress(translation, true);
|
||||
});
|
||||
|
||||
/*
|
||||
* closes items imported indicator
|
||||
*/
|
||||
translation.setHandler("done", function(obj, worked) {
|
||||
// add items to import collection
|
||||
if(importCollection) {
|
||||
importCollection.addItems(obj.newItems.map(item => item.id));
|
||||
}
|
||||
|
||||
Zotero.DB.commitTransaction();
|
||||
|
||||
Zotero_File_Interface.Progress.close();
|
||||
Zotero.UnresponsiveScriptIndicator.enable();
|
||||
|
||||
if(importCollection) {
|
||||
Zotero.Notifier.trigger('refresh', 'collection', importCollection.id);
|
||||
}
|
||||
if (!worked) {
|
||||
window.alert(Zotero.getString("fileInterface.importError"));
|
||||
}
|
||||
});
|
||||
Zotero.UnresponsiveScriptIndicator.disable();
|
||||
|
||||
// show progress indicator
|
||||
Zotero_File_Interface.Progress.show(
|
||||
Zotero.getString("fileInterface.itemsImported")
|
||||
);
|
||||
|
||||
window.setTimeout(function() {
|
||||
Zotero.DB.beginTransaction();
|
||||
translation.translate(libraryID);
|
||||
}, 0);
|
||||
} else {
|
||||
|
||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_OK)
|
||||
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING);
|
||||
var index = ps.confirmEx(
|
||||
null,
|
||||
"",
|
||||
Zotero.getString("fileInterface.unsupportedFormat"),
|
||||
buttonFlags,
|
||||
null,
|
||||
Zotero.getString("fileInterface.viewSupportedFormats"),
|
||||
null, null, {}
|
||||
);
|
||||
if (index == 1) {
|
||||
ZoteroPane_Local.loadURI("http://zotero.org/support/kb/importing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a bibliography from a collection or saved search
|
||||
*/
|
||||
function bibliographyFromCollection() {
|
||||
// find sorted items
|
||||
var items = Zotero.Items.get(ZoteroPane_Local.getSortedItems(true));
|
||||
if(!items) return;
|
||||
|
||||
// find name
|
||||
var name = false;
|
||||
|
||||
var collection = ZoteroPane_Local.getSelectedCollection();
|
||||
if(collection) {
|
||||
name = collection.getName();
|
||||
} else {
|
||||
var searchRef = ZoteroPane_Local.getSelectedSavedSearch();
|
||||
if(searchRef) {
|
||||
var search = new Zotero.Search();
|
||||
search.id = searchRef.id;
|
||||
name = search.name;
|
||||
}
|
||||
}
|
||||
|
||||
_doBibliographyOptions(name, items);
|
||||
return;
|
||||
|
||||
throw ("No collection or saved search currently selected");
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a bibliography from a items
|
||||
*/
|
||||
function bibliographyFromItems() {
|
||||
var items = ZoteroPane_Local.getSelectedItems();
|
||||
if(!items || !items.length) throw("no items currently selected");
|
||||
|
||||
_doBibliographyOptions(Zotero.getString("fileInterface.untitledBibliography"), items);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copies HTML and text bibliography entries for passed items in given style
|
||||
*
|
||||
* Does not check that items are actual references (and not notes or attachments)
|
||||
*/
|
||||
function copyItemsToClipboard(items, style, locale, asHTML, asCitations) {
|
||||
// copy to clipboard
|
||||
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Components.interfaces.nsITransferable);
|
||||
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Components.interfaces.nsIClipboard);
|
||||
var style = Zotero.Styles.get(style);
|
||||
var cslEngine = style.getCiteProc(locale);
|
||||
|
||||
// add HTML
|
||||
var bibliography = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "html", asCitations);
|
||||
var str = Components.classes["@mozilla.org/supports-string;1"].
|
||||
createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = bibliography;
|
||||
transferable.addDataFlavor("text/html");
|
||||
transferable.setTransferData("text/html", str, bibliography.length*2);
|
||||
|
||||
// add text (or HTML source)
|
||||
if(!asHTML) {
|
||||
cslEngine = style.getCiteProc(locale);
|
||||
var bibliography = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "text", asCitations);
|
||||
}
|
||||
var str = Components.classes["@mozilla.org/supports-string;1"].
|
||||
createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = bibliography;
|
||||
transferable.addDataFlavor("text/unicode");
|
||||
transferable.setTransferData("text/unicode", str, bibliography.length*2);
|
||||
|
||||
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copies HTML and text citations for passed items in given style
|
||||
*
|
||||
* Does not check that items are actual references (and not notes or attachments)
|
||||
*
|
||||
* if |asHTML| is true, copy HTML source as text
|
||||
*/
|
||||
function copyCitationToClipboard(items, style, locale, asHTML) {
|
||||
// copy to clipboard
|
||||
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Components.interfaces.nsITransferable);
|
||||
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Components.interfaces.nsIClipboard);
|
||||
|
||||
var style = Zotero.Styles.get(style).getCiteProc(locale);
|
||||
var citation = {
|
||||
citationItems: items.map(item => ({ id: item.id })),
|
||||
properties: {}
|
||||
};
|
||||
|
||||
// add HTML
|
||||
var bibliography = style.previewCitationCluster(citation, [], [], "html");
|
||||
var str = Components.classes["@mozilla.org/supports-string;1"].
|
||||
createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = bibliography;
|
||||
transferable.addDataFlavor("text/html");
|
||||
transferable.setTransferData("text/html", str, bibliography.length*2);
|
||||
|
||||
// add text (or HTML source)
|
||||
if(!asHTML) {
|
||||
var bibliography = style.previewCitationCluster(citation, [], [], "text");
|
||||
}
|
||||
var str = Components.classes["@mozilla.org/supports-string;1"].
|
||||
createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = bibliography;
|
||||
transferable.addDataFlavor("text/unicode");
|
||||
transferable.setTransferData("text/unicode", str, bibliography.length*2);
|
||||
|
||||
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shows bibliography options and creates a bibliography
|
||||
*/
|
||||
function _doBibliographyOptions(name, items) {
|
||||
// make sure at least one item is not a standalone note or attachment
|
||||
var haveRegularItem = false;
|
||||
for each(var item in items) {
|
||||
if (item.isRegularItem()) {
|
||||
haveRegularItem = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!haveRegularItem) {
|
||||
window.alert(Zotero.getString("fileInterface.noReferencesError"));
|
||||
return;
|
||||
}
|
||||
|
||||
var io = new Object();
|
||||
var newDialog = window.openDialog("chrome://zotero/content/bibliography.xul",
|
||||
"_blank","chrome,modal,centerscreen", io);
|
||||
|
||||
if(!io.method) return;
|
||||
|
||||
// determine output format
|
||||
var format = "html";
|
||||
if(io.method == "save-as-rtf") {
|
||||
format = "rtf";
|
||||
}
|
||||
|
||||
// determine locale preference
|
||||
var locale = io.locale;
|
||||
|
||||
// generate bibliography
|
||||
try {
|
||||
if(io.method == 'copy-to-clipboard') {
|
||||
Zotero_File_Interface.copyItemsToClipboard(items, io.style, locale, false, io.mode === "citations");
|
||||
}
|
||||
else {
|
||||
var style = Zotero.Styles.get(io.style);
|
||||
var cslEngine = style.getCiteProc(locale);
|
||||
var bibliography = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine,
|
||||
items, format, io.mode === "citations");
|
||||
}
|
||||
} catch(e) {
|
||||
window.alert(Zotero.getString("fileInterface.bibliographyGenerationError"));
|
||||
throw(e);
|
||||
}
|
||||
|
||||
if(io.method == "print") {
|
||||
// printable bibliography, using a hidden browser
|
||||
var browser = Zotero.Browser.createHiddenBrowser(window);
|
||||
|
||||
var listener = function() {
|
||||
if(browser.contentDocument.location.href == "about:blank") return;
|
||||
browser.removeEventListener("pageshow", listener, false);
|
||||
|
||||
// this is kinda nasty, but we have to temporarily modify the user's
|
||||
// settings to eliminate the header and footer. the other way to do
|
||||
// this would be to attempt to print with an embedded browser, but
|
||||
// it's not even clear how to attempt to create one
|
||||
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
var prefsToClear = ["print.print_headerleft", "print.print_headercenter",
|
||||
"print.print_headerright", "print.print_footerleft",
|
||||
"print.print_footercenter", "print.print_footerright"];
|
||||
var oldPrefs = [];
|
||||
for(var i in prefsToClear) {
|
||||
oldPrefs[i] = prefService.getCharPref(prefsToClear[i]);
|
||||
prefService.setCharPref(prefsToClear[i], "");
|
||||
}
|
||||
|
||||
// print
|
||||
browser.contentWindow.print();
|
||||
|
||||
// set the prefs back
|
||||
for(var i in prefsToClear) {
|
||||
prefService.setCharPref(prefsToClear[i], oldPrefs[i]);
|
||||
}
|
||||
|
||||
// TODO can't delete hidden browser object here or else print will fail...
|
||||
}
|
||||
|
||||
browser.addEventListener("pageshow", listener, false);
|
||||
browser.loadURIWithFlags("data:text/html;charset=utf-8,"+encodeURI(bibliography),
|
||||
Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, null, "utf-8", null);
|
||||
} else if(io.method == "save-as-html") {
|
||||
var fStream = _saveBibliography(name, "HTML");
|
||||
|
||||
if(fStream !== false) {
|
||||
var html = "";
|
||||
html +='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n';
|
||||
html +='<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n';
|
||||
html +='<head>\n';
|
||||
html +='<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>\n';
|
||||
html +='<title>'+Zotero.getString("fileInterface.bibliographyHTMLTitle")+'</title>\n';
|
||||
html +='</head>\n';
|
||||
html +='<body>\n';
|
||||
html += bibliography;
|
||||
html +='</body>\n';
|
||||
html +='</html>\n';
|
||||
|
||||
// create UTF-8 output stream
|
||||
var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
os.init(fStream, "UTF-8", 0, "?".charCodeAt(0));
|
||||
|
||||
os.writeString(html);
|
||||
|
||||
os.close();
|
||||
fStream.close();
|
||||
}
|
||||
} else if(io.method == "save-as-rtf") {
|
||||
var fStream = _saveBibliography(name, "RTF");
|
||||
if(fStream !== false) {
|
||||
fStream.write(bibliography, bibliography.length);
|
||||
fStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _saveBibliography(name, format) {
|
||||
// savable bibliography, using a file stream
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
||||
.createInstance(nsIFilePicker);
|
||||
fp.init(window, "Save Bibliography", nsIFilePicker.modeSave);
|
||||
|
||||
if(format == "RTF") {
|
||||
var extension = "rtf";
|
||||
fp.appendFilter("RTF", "*.rtf");
|
||||
} else {
|
||||
var extension = "html";
|
||||
fp.appendFilters(nsIFilePicker.filterHTML);
|
||||
}
|
||||
|
||||
fp.defaultString = name+"."+extension;
|
||||
|
||||
var rv = fp.show();
|
||||
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
|
||||
// open file
|
||||
var fStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
fStream.init(fp.file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
|
||||
return fStream;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates progress indicators based on current progress of translation
|
||||
*/
|
||||
this.updateProgress = function(translate, closeTransaction) {
|
||||
Zotero.updateZoteroPaneProgressMeter(translate.getProgress());
|
||||
|
||||
var now = Date.now();
|
||||
|
||||
// Don't repaint more than once per second unless forced.
|
||||
if(window.zoteroLastRepaint && (now - window.zoteroLastRepaint) < 1000) return
|
||||
|
||||
// Add the redraw event onto event queue
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.redraw();
|
||||
|
||||
// Process redraw event
|
||||
if(closeTransaction) Zotero.DB.commitTransaction();
|
||||
Zotero.wait();
|
||||
if(closeTransaction) Zotero.DB.beginTransaction();
|
||||
|
||||
window.zoteroLastRepaint = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Handles the display of a progress indicator
|
||||
Zotero_File_Interface.Progress = new function() {
|
||||
this.show = show;
|
||||
this.close = close;
|
||||
|
||||
function show(headline) {
|
||||
Zotero.showZoteroPaneProgressMeter(headline)
|
||||
}
|
||||
|
||||
function close() {
|
||||
Zotero.hideZoteroPaneOverlay();
|
||||
}
|
||||
}
|
305
chrome/content/zotero/icon.js
Normal file
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2015 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource:///modules/CustomizableUI.jsm");
|
||||
|
||||
var comboButtonsID = 'zotero-toolbar-buttons';
|
||||
|
||||
CustomizableUI.addListener({
|
||||
onWidgetAdded: function (id, area, position) {
|
||||
if (id == comboButtonsID) {
|
||||
// When dropping combo button into panel, add two independent buttons instead
|
||||
if (area == CustomizableUI.AREA_PANEL) {
|
||||
let mainID = getSingleID('main');
|
||||
let saveID = getSingleID('save');
|
||||
CustomizableUI.removeWidgetFromArea(id);
|
||||
// Remove independent main and save buttons first if they're already in panel
|
||||
CustomizableUI.removeWidgetFromArea(mainID);
|
||||
CustomizableUI.removeWidgetFromArea(saveID);
|
||||
CustomizableUI.addWidgetToArea(mainID, area, position);
|
||||
let placement = CustomizableUI.getPlacementOfWidget(mainID)
|
||||
let mainPos = placement.position;
|
||||
CustomizableUI.addWidgetToArea(saveID, area, mainPos + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
var isUpgrade = false;
|
||||
try {
|
||||
isUpgrade = Zotero.Prefs.get("firstRunGuidanceShown.saveIcon");
|
||||
} catch(e) {}
|
||||
var property = "firstRunGuidance.toolbarButton." + (isUpgrade ? "upgrade" : "new");
|
||||
var shortcut = Zotero.getString(
|
||||
Zotero.isMac ? "general.keys.cmdShift" : "general.keys.ctrlShift"
|
||||
) + Zotero.Prefs.get("keys.openZotero");
|
||||
|
||||
let widget = CustomizableUI.getWidget(id);
|
||||
for (let instance of widget.instances) {
|
||||
let doc = instance.node.ownerDocument;
|
||||
|
||||
updateItemForArea(instance.node, area);
|
||||
|
||||
doc.getElementById("zotero-main-button-guidance").show({
|
||||
text: Zotero.getString(property, shortcut)
|
||||
});
|
||||
doc.getElementById("zotero-save-button-guidance").show();
|
||||
}
|
||||
}
|
||||
else if (id == getSingleID('save')) {
|
||||
let widget = CustomizableUI.getWidget(id);
|
||||
for (let instance of widget.instances) {
|
||||
instance.node.ownerDocument.defaultView.Zotero_Browser.updateStatus();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onWidgetOverflow: function (node, container) {
|
||||
if (node.id == comboButtonsID) {
|
||||
node.classList.add("toolbarbutton-1");
|
||||
}
|
||||
},
|
||||
|
||||
onWidgetUnderflow: function (node, container) {
|
||||
if (node.id == comboButtonsID) {
|
||||
node.classList.remove("toolbarbutton-1");
|
||||
}
|
||||
},
|
||||
|
||||
// Save icon in panel isn't in DOM until menu is shown once and therefore isn't updated
|
||||
// on page loads, so update the icon status when the panel is first shown so that it
|
||||
// doesn't remain disabled
|
||||
onAreaNodeRegistered: function (area, node) {
|
||||
if (area == CustomizableUI.AREA_PANEL) {
|
||||
var placement = CustomizableUI.getPlacementOfWidget(comboButtonsID)
|
||||
var update = false;
|
||||
let singleID = getSingleID('save');
|
||||
if (placement && placement.area == CustomizableUI.AREA_PANEL) {
|
||||
update = true;
|
||||
}
|
||||
else {
|
||||
placement = CustomizableUI.getPlacementOfWidget(singleID);
|
||||
if (placement && placement.area == CustomizableUI.AREA_PANEL) {
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
if (update) {
|
||||
let widget = CustomizableUI.getWidget(singleID);
|
||||
for (let instance of widget.instances) {
|
||||
instance.node.ownerDocument.defaultView.Zotero_Browser.updateStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Create the combo buttons, which go in the toolbar by default
|
||||
CustomizableUI.createWidget({
|
||||
id: comboButtonsID,
|
||||
type: 'custom',
|
||||
label: 'Zotero',
|
||||
tooltiptext: "Zotero",
|
||||
defaultArea: CustomizableUI.AREA_NAVBAR,
|
||||
onBuild: function (document) {
|
||||
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
var item = document.createElementNS(kNSXUL, "toolbaritem");
|
||||
item.setAttribute("id", comboButtonsID);
|
||||
item.setAttribute("label", "Zotero (Combo)"); // TODO: localize
|
||||
// Set this as an attribute in addition to the property to make sure we can style correctly.
|
||||
item.setAttribute("removable", "true");
|
||||
item.classList.add("chromeclass-toolbar-additional");
|
||||
|
||||
['main', 'save'].map(button => {
|
||||
return {
|
||||
name: button,
|
||||
id: getID(button),
|
||||
tooltiptext: getTooltipText(button),
|
||||
oncommand: getCommand(button)
|
||||
};
|
||||
}).forEach(function(attribs, index) {
|
||||
if (index != 0) {
|
||||
item.appendChild(document.createElementNS(kNSXUL, "separator"));
|
||||
}
|
||||
let button = document.createElementNS(kNSXUL, "toolbarbutton");
|
||||
if (attribs.name == 'main') {
|
||||
button.setAttribute('label', Zotero.clientName);
|
||||
}
|
||||
else if (attribs.name == 'save') {
|
||||
button.setAttribute('label', Zotero.getString('ingester.saveToZotero'));
|
||||
button.setAttribute('disabled', 'true');
|
||||
button.setAttribute('type', 'menu-button');
|
||||
let menupopup = document.createElementNS(kNSXUL, "menupopup");
|
||||
menupopup.setAttribute('onpopupshowing', "Zotero_Browser.onStatusPopupShowing(event)");
|
||||
button.appendChild(menupopup);
|
||||
}
|
||||
delete attribs.name;
|
||||
setAttributes(button, attribs);
|
||||
item.appendChild(button);
|
||||
});
|
||||
|
||||
updateItemForArea(item, this.currentArea)
|
||||
|
||||
return item;
|
||||
}
|
||||
});
|
||||
|
||||
// Create the independent Z button, which isn't shown by default
|
||||
CustomizableUI.createWidget({
|
||||
id: getSingleID('main'),
|
||||
label: Zotero.clientName,
|
||||
tooltiptext: getTooltipText('main'),
|
||||
defaultArea: false,
|
||||
onCommand: function (event) {
|
||||
event.target.ownerDocument.defaultView.ZoteroOverlay.toggleDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
// Create the independent save button, which isn't shown by default
|
||||
CustomizableUI.createWidget({
|
||||
id: getSingleID('save'),
|
||||
label: Zotero.getString('ingester.saveToZotero'),
|
||||
tooltiptext: getTooltipText('save'),
|
||||
defaultArea: false,
|
||||
onCommand: function (event) {
|
||||
event.target.ownerDocument.defaultView.Zotero_Browser.scrapeThisPage(null, event);
|
||||
},
|
||||
onCreated: function (button) {
|
||||
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
button.setAttribute('disabled', 'true');
|
||||
button.setAttribute('type', 'menu-button');
|
||||
let menupopup = document.createElementNS(kNSXUL, "menupopup");
|
||||
menupopup.setAttribute('onpopupshowing', "Zotero_Browser.onStatusPopupShowing(event)");
|
||||
button.appendChild(menupopup);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function getID(button) {
|
||||
switch (button) {
|
||||
case 'main':
|
||||
return "zotero-toolbar-main-button";
|
||||
|
||||
case 'save':
|
||||
return "zotero-toolbar-save-button";
|
||||
}
|
||||
}
|
||||
|
||||
function getSingleID(button) {
|
||||
return getID(button) + '-single';
|
||||
}
|
||||
|
||||
function getCommand(button) {
|
||||
switch (button) {
|
||||
case 'main':
|
||||
return "ZoteroOverlay.toggleDisplay()";
|
||||
|
||||
case 'save':
|
||||
return "Zotero_Browser.scrapeThisPage(null, event)";
|
||||
}
|
||||
}
|
||||
|
||||
function getTooltipText(button) {
|
||||
var text;
|
||||
switch (button) {
|
||||
case 'main':
|
||||
if (Zotero && Zotero.initialized) {
|
||||
text = Zotero.clientName;
|
||||
let key = Zotero.Keys.getKeyForCommand('openZotero');
|
||||
if (key) {
|
||||
// Add RLE mark in RTL mode to make shortcut render the right way
|
||||
text += (Zotero.rtl ? ' \u202B' : ' ') + '('
|
||||
+ (Zotero.isMac ? '⇧⌘' : Zotero.getString('general.keys.ctrlShift'))
|
||||
+ key
|
||||
+ ')';
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (Zotero) {
|
||||
text = Zotero.startupError;
|
||||
}
|
||||
|
||||
// Use defaults if necessary
|
||||
if (!text) {
|
||||
// Get the stringbundle manually
|
||||
let src = 'chrome://zotero/locale/zotero.properties';
|
||||
let localeService = Components.classes['@mozilla.org/intl/nslocaleservice;1']
|
||||
.getService(Components.interfaces.nsILocaleService);
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
let stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Components.interfaces.nsIStringBundleService);
|
||||
let stringBundle = stringBundleService.createBundle(src);
|
||||
text = stringBundle.GetStringFromName('startupError');
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'save':
|
||||
text = Zotero.getString('ingester.saveToZotero');
|
||||
break;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set various attributes that allow treeitem and subelements to be styled properly
|
||||
* in the different areas
|
||||
*/
|
||||
function updateItemForArea(item, area) {
|
||||
if (area) {
|
||||
var areaType = CustomizableUI.getAreaType(area);
|
||||
var inPanel = area == CustomizableUI.AREA_PANEL;
|
||||
var classes = inPanel ? "panel-combined-button" : "toolbarbutton-1 toolbarbutton-combined";
|
||||
item.setAttribute("cui-areatype", areaType);
|
||||
item.classList.add("toolbaritem-combined-buttons");
|
||||
if (inPanel) {
|
||||
item.classList.add("panel-wide-item");
|
||||
}
|
||||
var buttons = item.getElementsByTagName('toolbarbutton');
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
let button = buttons[i];
|
||||
button.setAttribute("class", classes);
|
||||
button.setAttribute("cui-areatype", areaType);
|
||||
}
|
||||
}
|
||||
// In customization palette pretend it's a single icon
|
||||
else {
|
||||
item.classList.remove("toolbaritem-combined-buttons");
|
||||
item.classList.remove("panel-wide-item");
|
||||
var buttons = item.getElementsByTagName('toolbarbutton');
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
let button = buttons[i];
|
||||
button.setAttribute("class", "toolbarbutton-1");
|
||||
button.removeAttribute("cui-areatype");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAttributes(elem, attrs) {
|
||||
for (let i in attrs) {
|
||||
elem.setAttribute(i, attrs[i]);
|
||||
}
|
||||
}
|
5
chrome/content/zotero/include.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
var Zotero = Components.classes["@zotero.org/Zotero;1"]
|
||||
// Currently uses only nsISupports
|
||||
//.getService(Components.interfaces.chnmIZoteroService).
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
104
chrome/content/zotero/ingester/selectitems.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace Singleton to interface with the browser when ingesting data
|
||||
*/
|
||||
var Zotero_Ingester_Interface_SelectItems = function() {}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public Zotero_Ingester_Interface_SelectItems methods
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Presents items to select in the select box. Assumes window.arguments[0].dataIn is an object with
|
||||
* URLs as keys and descriptions as values
|
||||
*/
|
||||
Zotero_Ingester_Interface_SelectItems.init = function() {
|
||||
// Set font size from pref
|
||||
var sbc = document.getElementById('zotero-select-items-container');
|
||||
Zotero.setFontSize(sbc);
|
||||
|
||||
this.io = window.arguments[0];
|
||||
var listbox = document.getElementById("zotero-selectitems-links");
|
||||
|
||||
for(var i in this.io.dataIn) { // we could use a tree for this if we wanted to
|
||||
var item = this.io.dataIn[i];
|
||||
|
||||
var title, checked = false;
|
||||
if(item && typeof(item) == "object" && item.title !== undefined) {
|
||||
title = item.title;
|
||||
checked = !!item.checked;
|
||||
} else {
|
||||
title = item;
|
||||
}
|
||||
|
||||
var itemNode = document.createElement("listitem");
|
||||
itemNode.setAttribute("type", "checkbox");
|
||||
itemNode.setAttribute("value", i);
|
||||
itemNode.setAttribute("label", title);
|
||||
itemNode.setAttribute("checked", checked);
|
||||
listbox.appendChild(itemNode);
|
||||
}
|
||||
|
||||
// Check item if there is only one
|
||||
if (listbox.itemCount === 1) {
|
||||
listbox.getItemAtIndex(0).setAttribute("checked", true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects or deselects all items
|
||||
* @param {Boolean} deselect If true, deselect all items instead of selecting all items
|
||||
*/
|
||||
Zotero_Ingester_Interface_SelectItems.selectAll = function(deselect) {
|
||||
var listbox = document.getElementById("zotero-selectitems-links");
|
||||
for (var i=0; i<listbox.childNodes.length; i++){
|
||||
listbox.childNodes[i].setAttribute('checked', !deselect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when "OK" button is pressed to populate window.arguments[0].dataOut with selected items
|
||||
*/
|
||||
Zotero_Ingester_Interface_SelectItems.acceptSelection = function() {
|
||||
var listbox = document.getElementById("zotero-selectitems-links");
|
||||
|
||||
var returnObject = false;
|
||||
this.io.dataOut = new Object();
|
||||
|
||||
// collect scrapeURLList from listbox
|
||||
for(var i=0; i<listbox.childNodes.length; i++) {
|
||||
var itemNode = listbox.childNodes[i];
|
||||
if(itemNode.getAttribute("checked") == "true") {
|
||||
this.io.dataOut[itemNode.getAttribute("value")] = itemNode.getAttribute("label");
|
||||
returnObject = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!returnObject) this.io.dataOut = null;
|
||||
}
|
51
chrome/content/zotero/ingester/selectitems.xul
Executable file
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
<dialog xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&zotero.selectitems.title;" width="400" height="330"
|
||||
persist="width height screenX screenY"
|
||||
buttons="cancel,accept"
|
||||
ondialogaccept="Zotero_Ingester_Interface_SelectItems.acceptSelection()"
|
||||
id="zotero-selectitems"
|
||||
onload="Zotero_Ingester_Interface_SelectItems.init()">
|
||||
|
||||
<script src="../include.js"/>
|
||||
<script src="selectitems.js"/>
|
||||
|
||||
<vbox id="zotero-select-items-container" flex="1">
|
||||
<caption label="&zotero.selectitems.intro.label;" id="zotero-selectitems-intro"/>
|
||||
<box flex="1">
|
||||
<listbox id="zotero-selectitems-links" flex="1" context="zoteroSelectContext"></listbox>
|
||||
</box>
|
||||
<hbox>
|
||||
<button label="Select All" oncommand="Zotero_Ingester_Interface_SelectItems.selectAll()"/>
|
||||
<button label="Deselect All" oncommand="Zotero_Ingester_Interface_SelectItems.selectAll(true)"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</dialog>
|
803
chrome/content/zotero/integration/addCitationDialog.js
Normal file
|
@ -0,0 +1,803 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_Citation_Dialog = new function () {
|
||||
// Array value [0] is property name.
|
||||
// Array value [1] is default value of property.
|
||||
var _preserveData = {
|
||||
"prefix":["value", ""],
|
||||
"suffix":["value", ""],
|
||||
"label":["selectedIndex", 0],
|
||||
"locator":["value", ""],
|
||||
"suppress-author":["checked", false]
|
||||
};
|
||||
|
||||
var _accepted = false;
|
||||
var _itemData = new Object();
|
||||
var _multipleSourcesOn = false;
|
||||
var _lastSelected = null;
|
||||
var _previewShown = false;
|
||||
var _suppressNextTreeSelect = false;
|
||||
var _suppressNextListSelect = false;
|
||||
var _locatorIndexArray = {};
|
||||
var _locatorNameArray = {};
|
||||
var _autoRegeneratePref;
|
||||
var _acceptButton;
|
||||
var _multipleSourceButton;
|
||||
var _sortCheckbox;
|
||||
var _citationList;
|
||||
var _originalHTML;
|
||||
var serial_number;
|
||||
var io;
|
||||
|
||||
this.load = load;
|
||||
this.toggleMultipleSources = toggleMultipleSources;
|
||||
this.toggleEditor = toggleEditor;
|
||||
this.treeItemSelected = treeItemSelected;
|
||||
this.listItemSelected = listItemSelected;
|
||||
this.up = up;
|
||||
this.down = down;
|
||||
this.add = add;
|
||||
this.remove = remove;
|
||||
this.setSortToggle = setSortToggle;
|
||||
this.citationSortUnsort = citationSortUnsort;
|
||||
this.confirmRegenerate = confirmRegenerate;
|
||||
this.accept = accept;
|
||||
this.cancel = cancel;
|
||||
|
||||
/*
|
||||
* initialize add citation dialog
|
||||
*/
|
||||
function load() {
|
||||
// make sure we are visible
|
||||
window.setTimeout(function() {
|
||||
var screenX = window.screenX;
|
||||
var screenY = window.screenY;
|
||||
var xRange = [window.screen.availLeft, window.screen.width-window.outerWidth];
|
||||
var yRange = [window.screen.availTop, window.screen.height-window.outerHeight];
|
||||
if(screenX < xRange[0] || screenX > xRange[1] || screenY < yRange[0] || screenY > yRange[1]) {
|
||||
var targetX = Math.max(Math.min(screenX, xRange[1]), xRange[0]);
|
||||
var targetY = Math.max(Math.min(screenY, yRange[1]), yRange[0]);
|
||||
Zotero.debug("Moving window to "+targetX+", "+targetY);
|
||||
window.moveTo(targetX, targetY);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
document.documentElement.getButton("extra1").label = Zotero.getString("citation.multipleSources");
|
||||
document.documentElement.getButton("extra2").label = Zotero.getString("citation.showEditor");
|
||||
|
||||
io = window.arguments[0].wrappedJSObject;
|
||||
|
||||
// find accept button
|
||||
_acceptButton = document.getElementById("zotero-add-citation-dialog").getButton("accept");
|
||||
_multipleSourceButton = document.documentElement.getButton("extra1");
|
||||
_autoRegeneratePref = Zotero.Prefs.get("integration.autoRegenerate");
|
||||
_citationList = document.getElementById("citation-list");
|
||||
|
||||
// Manipulated by _addItem(). Discriminates between cite instances
|
||||
// based on the same item in the same citation. Internal throwaway variable,
|
||||
// reset each time _multipleSourcesOn is set to true.
|
||||
serial_number = 0;
|
||||
|
||||
// if a style with sortable citations, present checkbox
|
||||
if(io.sortable) {
|
||||
_sortCheckbox = document.getElementById("keepSorted");
|
||||
_sortCheckbox.hidden = false;
|
||||
_sortCheckbox.checked = !io.citation.properties.unsorted;
|
||||
}
|
||||
|
||||
// load locators
|
||||
var locators = Zotero.Cite.labels;
|
||||
var menu = document.getElementById("label");
|
||||
var label_list = document.getElementById("locator-type-popup");
|
||||
var i = 0;
|
||||
for(var value in locators) {
|
||||
var locator = locators[value];
|
||||
var locatorLabel = Zotero.getString('citation.locator.'+locator.replace(/\s/g,''));
|
||||
// add to list of labels
|
||||
var child = document.createElement("menuitem");
|
||||
child.setAttribute("value", value);
|
||||
child.setAttribute("label", locatorLabel);
|
||||
label_list.appendChild(child);
|
||||
// add to array
|
||||
_locatorIndexArray[locator] = i;
|
||||
_locatorNameArray[i] = locator;
|
||||
i++;
|
||||
}
|
||||
menu.selectedIndex = 0;
|
||||
|
||||
// load (from selectItemsDialog.js)
|
||||
doLoad();
|
||||
|
||||
// if we already have a citation, load data from it
|
||||
document.getElementById('editor').format = "RTF";
|
||||
if(io.citation.citationItems.length) {
|
||||
if(io.citation.citationItems.length === 1) {
|
||||
// single citation
|
||||
toggleMultipleSources(false);
|
||||
_suppressNextTreeSelect = true;
|
||||
|
||||
// If we're in a different library, switch libraries
|
||||
var id = io.citation.citationItems[0].id;
|
||||
var itemGroup = collectionsView._getItemAtRow(collectionsView.selection.currentIndex);
|
||||
var item = Zotero.Items.get(id);
|
||||
if(item.libraryID != itemGroup.ref.libraryID) {
|
||||
collectionsView.selectLibrary(item.libraryID);
|
||||
}
|
||||
var selected = itemsView.selectItem(id);
|
||||
if(!selected) {
|
||||
// If item wasn't found in current view, select library root
|
||||
// and try again (in case we were in a collection of correct library)
|
||||
collectionsView.selectLibrary(item.libraryID);
|
||||
itemsView.selectItem(id);
|
||||
}
|
||||
|
||||
for(var box in _preserveData) {
|
||||
var property = _preserveData[box][0];
|
||||
if(io.citation.citationItems[0][box]) {
|
||||
if(box === "label") {
|
||||
document.getElementById(box)[property] = _locatorIndexArray[io.citation.citationItems[0][box]];
|
||||
} else {
|
||||
document.getElementById(box)[property] = io.citation.citationItems[0][box];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// multiple citations
|
||||
toggleMultipleSources(true);
|
||||
var _itemData = {};
|
||||
// There is a little thrashing here, with repeated writes and
|
||||
// overwrites of node content. But sticking to the same
|
||||
// workflow for all updates (node -> array -> io.citation) makes
|
||||
// debugging a little less painful.
|
||||
for(var i=0; i<io.citation.citationItems.length; i++) {
|
||||
var item = Zotero.Items.get(io.citation.citationItems[i].id);
|
||||
if(item) {
|
||||
var itemNode = _addItem(item);
|
||||
var itemDataID = itemNode.getAttribute("value");
|
||||
_itemData[itemDataID] = {};
|
||||
for(var box in _preserveData) {
|
||||
var domBox = document.getElementById(box);
|
||||
var property = _preserveData[box][0];
|
||||
if("undefined" !== typeof io.citation.citationItems[i][box]) {
|
||||
if(box === "label") {
|
||||
domBox[property] = _locatorIndexArray[io.citation.citationItems[i][box]];
|
||||
} else {
|
||||
domBox[property] = io.citation.citationItems[i][box];
|
||||
}
|
||||
} else {
|
||||
domBox[property] = _preserveData[box][1];
|
||||
}
|
||||
}
|
||||
_itemSelected(itemDataID, true);
|
||||
}
|
||||
}
|
||||
for (var box in _preserveData) {
|
||||
document.getElementById(box).disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// show user-editable edited citation
|
||||
if(io.citation.properties.custom) {
|
||||
toggleEditor(io.citation.properties.custom);
|
||||
delete io.citation.properties.custom;
|
||||
}
|
||||
|
||||
_updateAccept();
|
||||
} else {
|
||||
toggleMultipleSources(false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on/off multiple sources item list
|
||||
*/
|
||||
function toggleMultipleSources(mode) {
|
||||
if (mode === false || mode === true) {
|
||||
_multipleSourcesOn = !mode;
|
||||
}
|
||||
_multipleSourcesOn = !_multipleSourcesOn;
|
||||
var popup = document.defaultView;
|
||||
var dialog = document.getElementById("zotero-add-citation-dialog");
|
||||
if (dialog.getAttribute("height") == 1) {
|
||||
popup.sizeToContent();
|
||||
}
|
||||
if(_multipleSourcesOn) {
|
||||
_multipleSourceButton.label = Zotero.getString("citation.singleSource");
|
||||
document.getElementById("multiple-sources").setAttribute("hidden", false);
|
||||
if(dialog.getAttribute("width") <= 600) {
|
||||
popup.resizeTo(750, dialog.getAttribute("height"));
|
||||
}
|
||||
//popup.moveBy((600 - 750)/2, 0);
|
||||
|
||||
serial_number = 0;
|
||||
|
||||
|
||||
// The mode is forced only when run from load(), in which case
|
||||
// the adding of items is done separately.
|
||||
if (mode !== true) {
|
||||
this.add(true);
|
||||
}
|
||||
} else {
|
||||
_multipleSourceButton.label = Zotero.getString("citation.multipleSources");
|
||||
document.getElementById("multiple-sources").setAttribute("hidden", true);
|
||||
//popup.resizeTo(600, dialog.getAttribute("height"));
|
||||
//popup.moveBy((750 - 600)/2, 0);
|
||||
|
||||
// enable all fields
|
||||
for(var box in _preserveData) {
|
||||
document.getElementById(box).disabled = false;
|
||||
}
|
||||
|
||||
var itemID = false;
|
||||
if (_citationList.selectedIndex > -1) {
|
||||
var itemDataID = _citationList.getSelectedItem(0).getAttribute("value");
|
||||
itemID = itemDataID.slice(0, itemDataID.indexOf(":"));
|
||||
}
|
||||
|
||||
// delete item list
|
||||
_itemData = new Object();
|
||||
|
||||
// delete all items
|
||||
_clearCitationList();
|
||||
|
||||
// refresh
|
||||
if (itemID) {
|
||||
itemsView.wrappedJSObject.selectItem(itemID);
|
||||
}
|
||||
_updateAccept();
|
||||
_updatePreview();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called when an item in the item selection tree is clicked
|
||||
*/
|
||||
function treeItemSelected() {
|
||||
if(_suppressNextTreeSelect) {
|
||||
_suppressNextTreeSelect = false;
|
||||
_updateAccept();
|
||||
return;
|
||||
}
|
||||
var items = itemsView.getSelectedItems(true); // treeview from xpcom/itemTreeView.js
|
||||
var itemID = (items.length ? items[0] : false);
|
||||
|
||||
if(_multipleSourcesOn) {
|
||||
// We can safely use itemID here, because none of these operations
|
||||
// affect selected items; this is all about the tree and navigation.
|
||||
|
||||
// turn off highlight in selected item list
|
||||
_suppressNextListSelect = true;
|
||||
document.getElementById("citation-list").selectedIndex = -1;
|
||||
|
||||
// disable all fields
|
||||
|
||||
for(var box in _preserveData) {
|
||||
document.getElementById(box).disabled = true;
|
||||
}
|
||||
|
||||
// disable adding nothing
|
||||
document.getElementById("add").disabled = !itemID;
|
||||
document.getElementById("remove").disabled = true;
|
||||
document.getElementById("up").disabled = true;
|
||||
document.getElementById("down").disabled = true;
|
||||
} else {
|
||||
for(var box in _preserveData) {
|
||||
document.getElementById(box).disabled = !itemID;
|
||||
}
|
||||
_updateAccept();
|
||||
_updatePreview();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called when an item in the selected items list is clicked
|
||||
*/
|
||||
function listItemSelected() {
|
||||
if(_suppressNextListSelect) {
|
||||
_suppressNextListSelect = false;
|
||||
_updateAccept();
|
||||
return;
|
||||
}
|
||||
var selectedListItem = _citationList.getSelectedItem(0);
|
||||
var selectedListIndex = _citationList.selectedIndex;
|
||||
var itemDataID = (selectedListItem ? selectedListItem.getAttribute("value") : false);
|
||||
_itemSelected(itemDataID);
|
||||
// turn off highlight in item tree
|
||||
_suppressNextTreeSelect = true;
|
||||
document.getElementById("zotero-items-tree").view.selection.clearSelection();
|
||||
document.getElementById("remove").disabled = !itemDataID;
|
||||
document.getElementById("add").disabled = true;
|
||||
_configListPosition(!itemDataID, selectedListIndex);
|
||||
}
|
||||
|
||||
function _configListPosition(flag, selectedListIndex) {
|
||||
if (selectedListIndex > 0) {
|
||||
document.getElementById("up").disabled = flag;
|
||||
} else {
|
||||
document.getElementById("up").disabled = true;
|
||||
}
|
||||
if (-1 < selectedListIndex && selectedListIndex < (_citationList.getRowCount() - 1)) {
|
||||
document.getElementById("down").disabled = flag;
|
||||
} else {
|
||||
document.getElementById("down").disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
function _move(direction) {
|
||||
// automatically uncheck sorted checkbox if user is rearranging citation
|
||||
if(_sortCheckbox && _sortCheckbox.checked) {
|
||||
_sortCheckbox.checked = false;
|
||||
setSortToggle();
|
||||
}
|
||||
|
||||
var insertBeforeItem;
|
||||
var selectedListItem = _citationList.getSelectedItem(0);
|
||||
var selectedListIndex = _citationList.selectedIndex;
|
||||
var itemDataID = selectedListItem.getAttribute("value");
|
||||
if (direction === -1) {
|
||||
insertBeforeItem = selectedListItem.previousSibling;
|
||||
} else {
|
||||
insertBeforeItem = selectedListItem.nextSibling.nextSibling;
|
||||
}
|
||||
var listItem = _citationList.removeChild(selectedListItem);
|
||||
_citationList.insertBefore(listItem, insertBeforeItem);
|
||||
_citationList.selectedIndex = (selectedListIndex + direction);
|
||||
_itemSelected(itemDataID);
|
||||
_updatePreview();
|
||||
_configListPosition(false, (selectedListIndex + direction));
|
||||
}
|
||||
|
||||
function up() {
|
||||
_move(-1);
|
||||
}
|
||||
|
||||
function down() {
|
||||
_move(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds an item to the multipleSources list
|
||||
*/
|
||||
function add(first_item) {
|
||||
|
||||
var pos, len;
|
||||
var item = itemsView.getSelectedItems()[0]; // treeview from xpcom/itemTreeView.js
|
||||
|
||||
if (!item) {
|
||||
sortCitation();
|
||||
_updateAccept();
|
||||
_updatePreview();
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to selection list and generate a new itemDataID for this cite.
|
||||
var selectionNode = _addItem(item);
|
||||
var itemDataID = selectionNode.getAttribute("value");
|
||||
document.getElementById("add").disabled = !itemDataID;
|
||||
|
||||
// Save existing locator and affix field content, if any.
|
||||
if (first_item) {
|
||||
_itemSelected(itemDataID, true);
|
||||
} else {
|
||||
_itemSelected();
|
||||
// set to defaults
|
||||
for(var box in _preserveData) {
|
||||
var property = _preserveData[box][0];
|
||||
var default_value = _preserveData[box][1];
|
||||
document.getElementById(box)[property] = default_value;
|
||||
}
|
||||
// Save default locator and affix element values to this multi-item.
|
||||
_itemSelected(itemDataID, true);
|
||||
}
|
||||
|
||||
for(var box in _preserveData) {
|
||||
document.getElementById(box).disabled = true;
|
||||
}
|
||||
|
||||
_citationList.ensureElementIsVisible(selectionNode);
|
||||
|
||||
// allow user to press OK
|
||||
selectionNode = sortCitation(selectionNode);
|
||||
_citationList.selectItem(selectionNode);
|
||||
_updateAccept();
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes a citation from the multipleSources list
|
||||
*/
|
||||
function remove() {
|
||||
var selectedListItem = _citationList.getSelectedItem(0);
|
||||
var selectedListIndex = _citationList.selectedIndex;
|
||||
var itemDataID = selectedListItem.getAttribute("value");
|
||||
|
||||
// remove from _itemData
|
||||
delete _itemData[itemDataID];
|
||||
_itemData[itemDataID] = undefined;
|
||||
_lastSelected = null;
|
||||
|
||||
// remove from list
|
||||
_citationList.removeChild(selectedListItem);
|
||||
|
||||
if (selectedListIndex >= _citationList.getRowCount()) {
|
||||
selectedListIndex = _citationList.getRowCount() - 1;
|
||||
}
|
||||
_citationList.selectedIndex = selectedListIndex;
|
||||
|
||||
_updateAccept();
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sorts preview citations, if preview is open.
|
||||
*/
|
||||
function citationSortUnsort() {
|
||||
setSortToggle();
|
||||
sortCitation();
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the current sort toggle state persistently on the citation.
|
||||
*/
|
||||
function setSortToggle() {
|
||||
if(!_sortCheckbox) return;
|
||||
if(!_sortCheckbox.checked) {
|
||||
io.citation.properties.unsorted = true;
|
||||
} else {
|
||||
io.citation.properties.unsorted = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sorts the list of citations
|
||||
*/
|
||||
function sortCitation(scrollToItem) {
|
||||
if(!_sortCheckbox) return scrollToItem;
|
||||
if(!_sortCheckbox.checked) {
|
||||
io.citation.properties.unsorted = true;
|
||||
return scrollToItem;
|
||||
}
|
||||
var scrollToItemID = false;
|
||||
if (scrollToItem) {
|
||||
scrollToItemID = scrollToItem.getAttribute("value");
|
||||
}
|
||||
_getCitation();
|
||||
|
||||
// delete all existing items from list
|
||||
_clearCitationList();
|
||||
|
||||
// run preview function to re-sort, if it hasn't already been
|
||||
// run
|
||||
io.sort();
|
||||
|
||||
// add items back to list
|
||||
scrollToItem = null;
|
||||
for(var i=0; i<io.citation.sortedItems.length; i++) {
|
||||
var itemID = io.citation.sortedItems[i][0].id;
|
||||
var itemDataID = io.citation.sortedItems[i][1].tmpItemDataID;
|
||||
var item = Zotero.Items.get(itemID);
|
||||
// Don't increment serial_number, and use the
|
||||
// existing itemDataID stored on the item in sortedItems
|
||||
var itemNode = _addItem(item, itemDataID);
|
||||
if(itemDataID == scrollToItemID) _citationList.selectedIndex = i;
|
||||
if(scrollToItemID && itemDataID == scrollToItemID) scrollToItem = itemNode;
|
||||
}
|
||||
|
||||
if(scrollToItem) _citationList.ensureElementIsVisible(scrollToItem);
|
||||
return scrollToItem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask whether to modifiy the preview
|
||||
*/
|
||||
function confirmRegenerate(focusShifted) {
|
||||
if(document.getElementById('editor').value == _originalHTML || _originalHTML === undefined) {
|
||||
// no changes; just update without asking
|
||||
_updatePreview();
|
||||
return;
|
||||
}
|
||||
|
||||
if(_autoRegeneratePref == -1) {
|
||||
if(focusShifted) { // only ask after onchange event; oninput is too
|
||||
// frequent for this to be worthwhile
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var saveBehavior = { value: false };
|
||||
var regenerate = promptService.confirmEx(
|
||||
this.window,
|
||||
Zotero.getString('integration.regenerate.title'),
|
||||
Zotero.getString('integration.regenerate.body'),
|
||||
promptService.STD_YES_NO_BUTTONS,
|
||||
null, null, null,
|
||||
Zotero.getString('integration.regenerate.saveBehavior'),
|
||||
saveBehavior
|
||||
);
|
||||
|
||||
if(saveBehavior.value) {
|
||||
_autoRegeneratePref = (regenerate == 0 ? 1 : 0);
|
||||
Zotero.Prefs.set("integration.autoRegenerate", _autoRegeneratePref);
|
||||
}
|
||||
|
||||
if(regenerate == 0) {
|
||||
_updatePreview();
|
||||
}
|
||||
}
|
||||
} else if(_autoRegeneratePref == 1) {
|
||||
_updatePreview();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shows the edit pane
|
||||
*/
|
||||
function toggleEditor(text) {
|
||||
var warning = document.getElementById('zotero-editor-warning');
|
||||
var editor = document.getElementById('editor');
|
||||
warning.hidden = _previewShown;
|
||||
editor.hidden = _previewShown;
|
||||
_previewShown = !_previewShown;
|
||||
|
||||
if(_previewShown) {
|
||||
document.documentElement.getButton("extra2").label = Zotero.getString("citation.hideEditor");
|
||||
if(text) {
|
||||
io.preview().then(function(preview) {
|
||||
_originalHTML = preview;
|
||||
editor.value = text;
|
||||
}).done();
|
||||
} else {
|
||||
_updatePreview();
|
||||
}
|
||||
} else {
|
||||
document.documentElement.getButton("extra2").label = Zotero.getString("citation.showEditor");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called when accept button is clicked
|
||||
*/
|
||||
function accept() {
|
||||
if(_accepted) return true;
|
||||
|
||||
_getCitation();
|
||||
var isCustom = _previewShown && io.citation.citationItems.length // if a citation is selected
|
||||
&& _originalHTML
|
||||
&& document.getElementById('editor').value != _originalHTML // and citation has been edited
|
||||
|
||||
if(isCustom) {
|
||||
var citation = document.getElementById('editor').value;
|
||||
if(Zotero.Utilities.trim(citation) == "") {
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
var insert = promptService.confirm(window,
|
||||
Zotero.getString("integration.emptyCitationWarning.title"),
|
||||
Zotero.getString("integration.emptyCitationWarning.body"));
|
||||
if(!insert) return false;
|
||||
}
|
||||
io.citation.properties.custom = citation;
|
||||
}
|
||||
|
||||
io.accept();
|
||||
_accepted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* called when cancel button is clicked
|
||||
*/
|
||||
function cancel() {
|
||||
if(_accepted) return true;
|
||||
io.citation.citationItems = new Array();
|
||||
|
||||
io.accept();
|
||||
_accepted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the contents of the preview pane
|
||||
*/
|
||||
function _updatePreview() {
|
||||
if(_previewShown) {
|
||||
var editor = document.getElementById('editor');
|
||||
_getCitation();
|
||||
|
||||
editor.readonly = !io.citation.citationItems.length;
|
||||
if(io.citation.citationItems.length) {
|
||||
io.preview().then(function(preview) {
|
||||
editor.value = preview;
|
||||
|
||||
if(editor.initialized) {
|
||||
_originalHTML = editor.value;
|
||||
} else {
|
||||
var eventListener = function() {
|
||||
_originalHTML = editor.value;
|
||||
editor.removeEventListener("tinymceInitialized", eventListener, false);
|
||||
};
|
||||
editor.addEventListener("tinymceInitialized", eventListener, false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
editor.value = "";
|
||||
_originalHTML = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Controls whether the accept (OK) button should be enabled
|
||||
*/
|
||||
function _updateAccept(status) {
|
||||
if(_multipleSourcesOn) {
|
||||
_acceptButton.disabled = !_citationList.getRowCount();
|
||||
// To prevent accidental data loss, do not allow change to
|
||||
// single citation mode if multiple items are in selection
|
||||
// list.
|
||||
if (_citationList.getRowCount() > 1) {
|
||||
_multipleSourceButton.disabled = true;
|
||||
} else {
|
||||
_multipleSourceButton.disabled = false;
|
||||
}
|
||||
} else {
|
||||
_acceptButton.disabled = !itemsView.getSelectedItems().length; // treeview from xpcom/itemTreeView.js
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called when an item is selected; if itemDataID is false, disables fields; if
|
||||
* itemDataID is undefined, only updates _itemData array
|
||||
*
|
||||
* Note: This function no longer disables fields. That operation is
|
||||
* now performed separately by explicit code.
|
||||
*/
|
||||
function _itemSelected(itemDataID, forceSave) {
|
||||
|
||||
if (forceSave) {
|
||||
_lastSelected = itemDataID;
|
||||
}
|
||||
|
||||
if(_lastSelected && !_itemData[_lastSelected]) {
|
||||
_itemData[_lastSelected] = new Object();
|
||||
}
|
||||
|
||||
for(var box in _preserveData) {
|
||||
var domBox = document.getElementById(box);
|
||||
var property = _preserveData[box][0];
|
||||
|
||||
// save property
|
||||
if(_lastSelected) {
|
||||
if(property == "label") {
|
||||
_itemData[_lastSelected][box] = _locatorNameArray[domBox.selectedIndex];
|
||||
} else {
|
||||
_itemData[_lastSelected][box] = domBox[property];
|
||||
}
|
||||
}
|
||||
// restore previous property
|
||||
if(itemDataID) {
|
||||
domBox.disabled = false;
|
||||
if(_itemData[itemDataID] && _itemData[itemDataID][box] !== undefined) {
|
||||
if(property == "label") {
|
||||
domBox[property] = _locatorIndexArray[_itemData[itemDataID][box]];
|
||||
} else {
|
||||
domBox[property] = _itemData[itemDataID][box];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(itemDataID !== undefined) _lastSelected = itemDataID;
|
||||
}
|
||||
|
||||
/*
|
||||
* updates io.citation to reflect selected items
|
||||
*/
|
||||
function _getCitation() {
|
||||
var key;
|
||||
io.citation.citationItems = new Array();
|
||||
|
||||
// use to map selectedIndexes back to page/paragraph/line
|
||||
var locatorTypeElements = document.getElementById("label").getElementsByTagName("menuitem");
|
||||
if(_multipleSourcesOn) {
|
||||
_itemSelected(); // store locator info
|
||||
var listLength = _citationList.getRowCount();
|
||||
if(listLength) {
|
||||
// generate citationItems
|
||||
for(var i=0; i<listLength; i++) {
|
||||
var itemDataID = _citationList.getItemAtIndex(i).getAttribute("value");
|
||||
var citationItem = {};
|
||||
for (key in _itemData[itemDataID]) {
|
||||
// label is special everywhere
|
||||
if (key === "label") {
|
||||
citationItem.label = _locatorNameArray[_itemData[itemDataID].label];
|
||||
} else if (_itemData[itemDataID][key]) {
|
||||
citationItem[key] = _itemData[itemDataID][key];
|
||||
}
|
||||
}
|
||||
citationItem["tmpItemDataID"] = itemDataID;
|
||||
var itemID = itemDataID.slice(0, itemDataID.indexOf(":"));
|
||||
citationItem.id = itemID;
|
||||
io.citation.citationItems.push(citationItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var items = itemsView.getSelectedItems(true); // treeview from xpcom/itemTreeView.js
|
||||
|
||||
if(items.length) {
|
||||
var citationItem = {};
|
||||
citationItem.id = items[0];
|
||||
for(var box in _preserveData) {
|
||||
var property = _preserveData[box][0];
|
||||
if(box == "label") {
|
||||
citationItem[box] = _locatorNameArray[document.getElementById(box).selectedIndex];
|
||||
} else {
|
||||
var prop = document.getElementById(box)[property];
|
||||
if(prop !== "" && prop !== false) citationItem[box] = prop;
|
||||
}
|
||||
}
|
||||
|
||||
if(!citationItem["locator"]) {
|
||||
delete citationItem["locator"];
|
||||
delete citationItem["label"];
|
||||
}
|
||||
|
||||
io.citation.citationItems = [citationItem];
|
||||
} else {
|
||||
io.citation.citationItems = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an item to the item list (multiple sources only)
|
||||
*/
|
||||
function _addItem(item, forceID) {
|
||||
var itemNode = document.createElement("listitem");
|
||||
|
||||
var itemDataID;
|
||||
if (!forceID) {
|
||||
serial_number += 1;
|
||||
itemDataID = item.id + ":" + serial_number;
|
||||
} else {
|
||||
itemDataID = forceID;
|
||||
}
|
||||
|
||||
itemNode.setAttribute("value", itemDataID);
|
||||
itemNode.setAttribute("label", item.getDisplayTitle());
|
||||
itemNode.setAttribute("class", "listitem-iconic");
|
||||
itemNode.setAttribute("image", item.getImageSrc());
|
||||
_citationList.appendChild(itemNode);
|
||||
return itemNode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes all items from the multiple sources list
|
||||
*/
|
||||
function _clearCitationList() {
|
||||
while(_citationList.firstChild) _citationList.removeChild(_citationList.firstChild);
|
||||
}
|
||||
}
|
291
chrome/content/zotero/integration/addCitationDialog.xul
Normal file
|
@ -0,0 +1,291 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/dialog.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/overlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/integration.css" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<dialog
|
||||
id="zotero-add-citation-dialog"
|
||||
windowtype="zotero:item-selector"
|
||||
orient="vertical"
|
||||
title="&zotero.integration.addEditCitation.title;"
|
||||
width="600" height="450"
|
||||
onload="Zotero_Citation_Dialog.load();"
|
||||
onunload="doUnload();"
|
||||
ondialogaccept="return Zotero_Citation_Dialog.accept();"
|
||||
ondialogcancel="Zotero_Citation_Dialog.cancel();"
|
||||
onclose="Zotero_Citation_Dialog.cancel();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
persist="screenX screenY width height"
|
||||
resizable="true"
|
||||
buttons="extra1,extra2,accept,cancel"
|
||||
ondialogextra2="Zotero_Citation_Dialog.toggleEditor()"
|
||||
ondialogextra1="Zotero_Citation_Dialog.toggleMultipleSources()">
|
||||
|
||||
<script src="../include.js"/>
|
||||
<script src="../selectItemsDialog.js"/>
|
||||
<script src="addCitationDialog.js"/>
|
||||
|
||||
<vbox id="zotero-select-items-container" flex="1">
|
||||
<vbox flex="1">
|
||||
<hbox flex="1">
|
||||
<vbox align="stretch" flex="1">
|
||||
<hbox align="center" pack="end">
|
||||
<textbox id="zotero-tb-search" type="search" timeout="250" oncommand="onSearch()" tabindex="1"
|
||||
onkeypress="if(event.keyCode == event.DOM_VK_ESCAPE) { if (this.value == '') { cancelDialog(); return false; } this.value = ''; onSearch(); return false; } return true;"/>
|
||||
</hbox>
|
||||
<hbox flex="1" style="margin-top: 5px">
|
||||
<tree id="zotero-collections-tree"
|
||||
style="width: 200px;" hidecolumnpicker="true" seltype="cell"
|
||||
onselect="onCollectionSelected();">
|
||||
<treecols>
|
||||
<treecol
|
||||
id="zotero-collections-name-column"
|
||||
flex="1"
|
||||
primary="true"
|
||||
hideheader="true"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
||||
<tree id="zotero-items-tree"
|
||||
enableColumnDrag="true" flex="1" seltype="single"
|
||||
onselect="Zotero_Citation_Dialog.treeItemSelected();">
|
||||
<treecols id="zotero-items-columns-header">
|
||||
<treecol
|
||||
id="zotero-items-column-title" primary="true"
|
||||
label="&zotero.items.title_column;"
|
||||
flex="4" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-firstCreator"
|
||||
label="&zotero.items.creator_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-itemType" hidden="true"
|
||||
label="&zotero.items.type_column;"
|
||||
width="40" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-date" hidden="true"
|
||||
label="&zotero.items.date_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-year" hidden="true"
|
||||
label="&zotero.items.year_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-publisher" hidden="true"
|
||||
label="&zotero.items.publisher_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-publicationTitle" hidden="true"
|
||||
label="&zotero.items.publication_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-journalAbbreviation" hidden="true"
|
||||
label="&zotero.items.journalAbbr_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-language" hidden="true"
|
||||
label="&zotero.items.language_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-accessDate" hidden="true"
|
||||
label="&zotero.items.accessDate_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-libraryCatalog" hidden="true"
|
||||
label="&zotero.items.libraryCatalog_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-callNumber" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.callNumber_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-rights" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.rights_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-dateAdded" hidden="true"
|
||||
label="&zotero.items.dateAdded_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-dateModified" hidden="true"
|
||||
label="&zotero.items.dateModified_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-archive" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.archive_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-archiveLocation" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.archiveLocation_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-place" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.place_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-volume" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.volume_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-edition" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.edition_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-pages" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.pages_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-issue" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.issue_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-series" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.series_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-seriesTitle" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.seriesTitle_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-court" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.court_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-medium" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.medium_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-genre" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.genre_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-system" hidden="true"
|
||||
submenu="true"
|
||||
label="&zotero.items.system_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-extra" hidden="true"
|
||||
label="&zotero.items.extra_column;"
|
||||
flex="1" zotero-persist="width ordinal hidden sortActive sortDirection"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<hbox hidden="true" id="multiple-sources" align="stretch">
|
||||
<vbox align="center" pack="center" id="citation-buttons">
|
||||
<toolbarbutton id="up" oncommand="Zotero_Citation_Dialog.up()" disabled="true"/>
|
||||
<toolbarbutton id="add" oncommand="Zotero_Citation_Dialog.add()" disabled="true"/>
|
||||
<toolbarbutton id="remove" oncommand="Zotero_Citation_Dialog.remove()" disabled="true"/>
|
||||
<toolbarbutton id="down" oncommand="Zotero_Citation_Dialog.down()" disabled="true"/>
|
||||
</vbox>
|
||||
<vbox align="left">
|
||||
<checkbox id="keepSorted" hidden="true" checked="false" oncommand="Zotero_Citation_Dialog.citationSortUnsort()" label="&zotero.citation.keepSorted.label;"/>
|
||||
<listbox id="citation-list" flex="1" align="stretch" seltype="single"
|
||||
onselect="Zotero_Citation_Dialog.listItemSelected();"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<hbox align="stretch" style="margin-top: 8px">
|
||||
<vbox flex="1">
|
||||
<hbox align="center">
|
||||
<label value="&zotero.citation.prefix.label;"/>
|
||||
<textbox oninput="Zotero_Citation_Dialog.confirmRegenerate(false)" onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" class="fix" id="prefix" align="stretch" flex="1" tabindex="3"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<label value="&zotero.citation.suffix.label;"/>
|
||||
<textbox oninput="Zotero_Citation_Dialog.confirmRegenerate(false)" onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" class="fix" id="suffix" align="stretch" flex="1" tabindex="4"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
</vbox>
|
||||
<separator flex="4"/>
|
||||
<vbox flex="1">
|
||||
<hbox align="stretch">
|
||||
<menulist onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" id="label" tabindex="5">
|
||||
<menupopup id="locator-type-popup"/>
|
||||
</menulist>
|
||||
<textbox oninput="Zotero_Citation_Dialog.confirmRegenerate(false)" onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" id="locator" tabindex="2" flex="1"/>
|
||||
</hbox>
|
||||
<separator style="height: 2px" flex="1"/>
|
||||
<checkbox oncommand="Zotero_Citation_Dialog.confirmRegenerate(true)" id="suppress-author" label="&zotero.citation.suppressAuthor.label;" tabindex="6"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<textbox id="editor" type="styled" mode="integration" hidden="true" flex="1"/>
|
||||
<description id="zotero-editor-warning" style="margin: 9px 1px 0" hidden="true">&zotero.citation.editorWarning.label;</description>
|
||||
</vbox>
|
||||
</dialog>
|
328
chrome/content/zotero/integration/editBibliographyDialog.js
Normal file
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_Bibliography_Dialog = new function () {
|
||||
var bibEditInterface;
|
||||
var _lastSelectedItemID = false;
|
||||
var _lastSelectedIndex = false;
|
||||
var _lastSelectedValue = false;
|
||||
var _accepted = false;
|
||||
var _revertButton, _revertAllButton, _addButton, _removeButton;
|
||||
var _itemList;
|
||||
var _suppressAllSelectEvents = false;
|
||||
|
||||
/**
|
||||
* Initializes add citation dialog
|
||||
*/
|
||||
this.load = function() {
|
||||
bibEditInterface = window.arguments[0].wrappedJSObject;
|
||||
|
||||
_revertAllButton = document.documentElement.getButton("extra2");
|
||||
_revertButton = document.documentElement.getButton("extra1");
|
||||
_addButton = document.getElementById("add");
|
||||
_removeButton = document.getElementById("remove");
|
||||
_itemList = document.getElementById("item-list");
|
||||
_itemTree = document.getElementById("zotero-items-tree");
|
||||
|
||||
_revertAllButton.label = Zotero.getString("integration.revertAll.button");
|
||||
_revertAllButton.disabled = bibEditInterface.isAnyEdited();
|
||||
_revertButton.label = Zotero.getString("integration.revert.button");
|
||||
_revertButton.disabled = true;
|
||||
|
||||
document.getElementById('editor').format = "RTF";
|
||||
|
||||
// load (from selectItemsDialog.js)
|
||||
doLoad();
|
||||
|
||||
// load bibliography entires
|
||||
_loadItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item in the item selection tree is clicked
|
||||
*/
|
||||
this.treeItemSelected = function() {
|
||||
if(_suppressAllSelectEvents) return;
|
||||
var selectedItemIDs = itemsView.getSelectedItems(true); // treeview from selectItemsDialog.js
|
||||
|
||||
// if all selected items are available in the list box on the right, select them there
|
||||
// otherwise, clear the list box selection
|
||||
var clearListItems = false;
|
||||
var itemsToSelect = [];
|
||||
if(selectedItemIDs.length) {
|
||||
for each(var itemID in selectedItemIDs) {
|
||||
var itemIndexToSelect = false;
|
||||
for(var i in bibEditInterface.bibliography[0].entry_ids) {
|
||||
if(bibEditInterface.bibliography[0].entry_ids[i].indexOf(itemID) !== -1) {
|
||||
itemIndexToSelect = i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(itemIndexToSelect !== false) {
|
||||
itemsToSelect.push(_itemList.getItemAtIndex(itemIndexToSelect));
|
||||
} else {
|
||||
clearListItems = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_suppressAllSelectEvents = true;
|
||||
_itemList.clearSelection();
|
||||
if(clearListItems) {
|
||||
_addButton.disabled = (itemsToSelect.length > 0);
|
||||
_revertButton.disabled = _removeButton.disabled = true;
|
||||
} else {
|
||||
_addButton.disabled = true;
|
||||
_removeButton.disabled = false;
|
||||
_updateRevertButtonStatus();
|
||||
itemsToSelect.forEach(item => _itemList.toggleItemSelection(item));
|
||||
_itemList.ensureIndexIsVisible(itemsToSelect[0]);
|
||||
}
|
||||
_suppressAllSelectEvents = false;
|
||||
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item in the reference list is clicked
|
||||
*/
|
||||
this.listItemSelected = function() {
|
||||
if(_suppressAllSelectEvents) return;
|
||||
|
||||
// enable remove if at least one item is selected
|
||||
_addButton.disabled = true;
|
||||
_removeButton.disabled = !_itemList.selectedItems.length;
|
||||
|
||||
if(_itemList.selectedItems.length) {
|
||||
_suppressAllSelectEvents = true;
|
||||
_itemTree.view.selection.clearSelection();
|
||||
_suppressAllSelectEvents = false;
|
||||
|
||||
// only show revert button if at least one selected item has been edited
|
||||
_updateRevertButtonStatus();
|
||||
}
|
||||
|
||||
// update preview to blank if no items or multiple items are selected; otherwise show
|
||||
// preview for selected items
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds references to the reference list
|
||||
*/
|
||||
this.add = function() {
|
||||
for each(var itemID in itemsView.getSelectedItems(true)) {
|
||||
bibEditInterface.add(itemID);
|
||||
}
|
||||
document.getElementById("add").disabled = true;
|
||||
_loadItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all customizations
|
||||
*/
|
||||
this.revertAll = function() {
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var out = {};
|
||||
var regenerate = promptService.confirmEx(
|
||||
window,
|
||||
Zotero.getString('integration.revertAll.title'),
|
||||
Zotero.getString('integration.revertAll.body'),
|
||||
promptService.STD_OK_CANCEL_BUTTONS+promptService.BUTTON_POS_1_DEFAULT,
|
||||
null, null, null, null, out
|
||||
);
|
||||
|
||||
if(regenerate != 0) return;
|
||||
|
||||
bibEditInterface.revertAll();
|
||||
|
||||
_loadItems();
|
||||
_updatePreview(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears customizations to selected entry
|
||||
*/
|
||||
this.revert = function() {
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var out = {};
|
||||
var regenerate = promptService.confirmEx(
|
||||
window,
|
||||
Zotero.getString('integration.revert.title'),
|
||||
Zotero.getString('integration.revert.body'),
|
||||
promptService.STD_OK_CANCEL_BUTTONS+promptService.BUTTON_POS_1_DEFAULT,
|
||||
null, null, null, null, out
|
||||
);
|
||||
|
||||
if(regenerate != 0) return;
|
||||
|
||||
for each(var itemID in _getSelectedListItemIDs()) {
|
||||
bibEditInterface.revert(itemID);
|
||||
}
|
||||
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes selected references from the reference list
|
||||
*/
|
||||
this.remove = function() {
|
||||
var selectedListItemIDs = _getSelectedListItemIDs();
|
||||
|
||||
// if cited in bibliography, warn before removing
|
||||
var isCited = false;
|
||||
for each(var itemID in selectedListItemIDs) {
|
||||
isCited |= bibEditInterface.isCited(itemID);
|
||||
}
|
||||
if(isCited) {
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var out = {};
|
||||
var regenerate = promptService.confirmEx(
|
||||
window,
|
||||
Zotero.getString('integration.removeBibEntry.title'),
|
||||
Zotero.getString('integration.removeBibEntry.body'),
|
||||
promptService.STD_OK_CANCEL_BUTTONS+promptService.BUTTON_POS_1_DEFAULT,
|
||||
null, null, null, null, out
|
||||
);
|
||||
if(regenerate != 0) return;
|
||||
}
|
||||
|
||||
// remove
|
||||
for each(var itemID in selectedListItemIDs) {
|
||||
bibEditInterface.remove(itemID);
|
||||
}
|
||||
_loadItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user edits the currently selected bibliography entry
|
||||
*/
|
||||
this.textChanged = function() {
|
||||
_revertButton.disabled = _revertAllButton.disabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when OK button is pressed
|
||||
*/
|
||||
this.accept = function() {
|
||||
if(_accepted) return;
|
||||
_updatePreview(true);
|
||||
_accepted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when Cancel button is pressed
|
||||
*/
|
||||
this.close = function() {
|
||||
if(_accepted) return;
|
||||
bibEditInterface.cancel();
|
||||
_accepted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets selected item IDs from list box on right
|
||||
*/
|
||||
function _getSelectedListItemIDs() {
|
||||
return Array.from(_itemList.selectedItems)
|
||||
.map(item => bibEditInterface.bibliography[0].entry_ids[item.value][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update status of "Revert" button to match modification status of current item
|
||||
*/
|
||||
function _updateRevertButtonStatus() {
|
||||
_revertButton.disabled = true;
|
||||
var selectedListItemIDs = _getSelectedListItemIDs();
|
||||
for each(var itemID in selectedListItemIDs) {
|
||||
if(bibEditInterface.isEdited(itemID)) {
|
||||
_revertButton.disabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contents of the preview pane
|
||||
*/
|
||||
function _updatePreview(ignoreSelection) {
|
||||
var index = !ignoreSelection && _itemList.selectedItems.length == 1 ? _itemList.selectedIndex : undefined;
|
||||
var editor = document.getElementById('editor');
|
||||
|
||||
if(_lastSelectedItemID) {
|
||||
var newValue = editor.value;
|
||||
if(_lastSelectedValue != newValue) {
|
||||
bibEditInterface.setCustomText(_lastSelectedItemID, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
editor.readonly = index === undefined;
|
||||
if(index !== undefined) {
|
||||
var itemID = bibEditInterface.bibliography[0].entry_ids[index];
|
||||
editor.value = bibEditInterface.bibliography[1][index];
|
||||
_lastSelectedIndex = index;
|
||||
_lastSelectedItemID = itemID;
|
||||
_lastSelectedValue = editor.value;
|
||||
} else {
|
||||
editor.value = "";
|
||||
_lastSelectedIndex = _lastSelectedItemID = _lastSelectedValue = false;
|
||||
}
|
||||
|
||||
_revertAllButton.disabled = !bibEditInterface.isAnyEdited();
|
||||
}
|
||||
|
||||
/*
|
||||
* loads items from itemSet
|
||||
*/
|
||||
function _loadItems() {
|
||||
var itemIDs = bibEditInterface.bibliography[0].entry_ids;
|
||||
var items = itemIDs.map(itemID => Zotero.Cite.getItem(itemID[0]));
|
||||
|
||||
// delete all existing items from list
|
||||
var itemList = document.getElementById("item-list");
|
||||
while(itemList.firstChild) {
|
||||
itemList.removeChild(itemList.firstChild);
|
||||
}
|
||||
|
||||
// add new items
|
||||
for(var i=0; i<items.length; i++) {
|
||||
var itemNode = document.createElement("listitem");
|
||||
itemNode.setAttribute("value", i);
|
||||
itemNode.setAttribute("label", items[i].getDisplayTitle());
|
||||
itemNode.setAttribute("class", "listitem-iconic");
|
||||
itemNode.setAttribute("image", items[i].getImageSrc());
|
||||
itemList.appendChild(itemNode);
|
||||
}
|
||||
|
||||
_updatePreview();
|
||||
}
|
||||
}
|
123
chrome/content/zotero/integration/editBibliographyDialog.xul
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/overlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/integration.css" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<dialog
|
||||
id="zotero-edit-bibliography-dialog"
|
||||
orient="vertical"
|
||||
title="&zotero.integration.editBibliography.title;"
|
||||
width="750" height="450"
|
||||
onload="Zotero_Bibliography_Dialog.load();"
|
||||
ondialogaccept="Zotero_Bibliography_Dialog.accept();"
|
||||
ondialogcancel="Zotero_Bibliography_Dialog.close();"
|
||||
onclose="Zotero_Bibliography_Dialog.close();"
|
||||
onunload="doUnload();"
|
||||
buttons="extra1,extra2,accept,cancel" buttonpack="end"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
persist="screenX screenY width height"
|
||||
resizable="true"
|
||||
ondialogextra1="Zotero_Bibliography_Dialog.revert()"
|
||||
ondialogextra2="Zotero_Bibliography_Dialog.revertAll()">
|
||||
|
||||
<script src="../include.js"/>
|
||||
<script src="../selectItemsDialog.js"/>
|
||||
<script src="editBibliographyDialog.js"/>
|
||||
|
||||
<vbox id="zotero-select-items-container" flex="1">
|
||||
<vbox flex="1">
|
||||
<hbox flex="1">
|
||||
<vbox align="stretch" flex="1">
|
||||
<hbox align="center" pack="end">
|
||||
<textbox id="zotero-tb-search" type="search" timeout="250" oncommand="onSearch()" dir="reverse" onkeypress="if(event.keyCode == event.DOM_VK_ESCAPE) { this.value = ''; this.doCommand('cmd_zotero_search'); return false; } return true;"/>
|
||||
</hbox>
|
||||
<hbox flex="1" style="margin-top: 5px">
|
||||
<tree id="zotero-collections-tree"
|
||||
style="width: 150px;" hidecolumnpicker="true" seltype="single"
|
||||
onselect="onCollectionSelected();">
|
||||
<treecols>
|
||||
<treecol
|
||||
id="zotero-collections-name-column"
|
||||
flex="1"
|
||||
primary="true"
|
||||
hideheader="true"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
||||
<tree id="zotero-items-tree"
|
||||
flex="1" hidecolumnpicker="true" seltype="multiple"
|
||||
onselect="Zotero_Bibliography_Dialog.treeItemSelected();">
|
||||
<treecols>
|
||||
<treecol
|
||||
id="zotero-items-column-title" primary="true"
|
||||
label="&zotero.items.title_column;"
|
||||
flex="4" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-firstCreator"
|
||||
label="&zotero.items.creator_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-dateAdded" hidden="true"
|
||||
label="&zotero.items.dateAdded_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol
|
||||
id="zotero-items-column-dateModified" hidden="true"
|
||||
label="&zotero.items.dateModified_column;"
|
||||
flex="1" persist="width ordinal hidden sortActive sortDirection"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<hbox id="source-list">
|
||||
<vbox align="center" pack="center" id="citation-buttons">
|
||||
<toolbarbutton id="add" oncommand="Zotero_Bibliography_Dialog.add()" disabled="true"/>
|
||||
<toolbarbutton id="remove" oncommand="Zotero_Bibliography_Dialog.remove()" disabled="true"/>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<label value="&zotero.integration.references.label;"/>
|
||||
<listbox id="item-list" flex="1" align="stretch" seltype="multiple"
|
||||
style="width: 250px;" onselect="Zotero_Bibliography_Dialog.listItemSelected();"
|
||||
onchanged="Zotero_Bibliography_Dialog.textChanged()"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<textbox id="editor" type="styled" mode="integration" flex="1"/>
|
||||
<description id="zotero-editor-warning" style="margin: 9px 1px 0">&zotero.citation.editorWarning.label;</description>
|
||||
</vbox>
|
||||
</dialog>
|
87
chrome/content/zotero/integration/integrationDocPrefs.xul
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/bibliography.css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<dialog
|
||||
id="zotero-doc-prefs-dialog"
|
||||
orient="vertical"
|
||||
buttons="accept,cancel"
|
||||
title="&zotero.integration.docPrefs.title;"
|
||||
onload="Zotero_File_Interface_Bibliography.init();"
|
||||
ondialogaccept="Zotero_File_Interface_Bibliography.acceptSelection();"
|
||||
onclose="document.documentElement.cancelDialog(); event.preventDefault(); event.stopPropagation();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
persist="screenX screenY"
|
||||
style="width: 600px">
|
||||
|
||||
<script src="../include.js"/>
|
||||
<script src="../bibliography.js"/>
|
||||
<vbox id="zotero-bibliography-container">
|
||||
<groupbox>
|
||||
<caption label="&zotero.bibliography.style.label;"/>
|
||||
<listbox id="style-listbox" onselect="Zotero_File_Interface_Bibliography.styleChanged()"/>
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<hbox align="center">
|
||||
<caption label="&zotero.bibliography.locale.label;"/>
|
||||
<menulist id="locale-menu" oncommand="Zotero_File_Interface_Bibliography.localeChanged(this.selectedItem.value)"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="displayAs-groupbox">
|
||||
<caption label="&zotero.integration.prefs.displayAs.label;"/>
|
||||
<radiogroup id="displayAs" orient="horizontal">
|
||||
<radio id="footnotes" label="&zotero.integration.prefs.footnotes.label;" selected="true"/>
|
||||
<radio id="endnotes" label="&zotero.integration.prefs.endnotes.label;"/>
|
||||
</radiogroup>
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&zotero.integration.prefs.formatUsing.label;"/>
|
||||
|
||||
<radiogroup id="formatUsing" orient="vertical">
|
||||
<radio id="fields" selected="true"/>
|
||||
<label class="radioDescription" id="fields-caption"/>
|
||||
<label class="radioDescription" id="fields-file-format-notice"/>
|
||||
<radio id="bookmarks" label="&zotero.integration.prefs.bookmarks.label;"/>
|
||||
<description class="radioDescription" id="bookmarks-caption">&zotero.integration.prefs.bookmarks.caption;</description>
|
||||
<description class="radioDescription" id="bookmarks-file-format-notice"/>
|
||||
</radiogroup>
|
||||
</groupbox>
|
||||
|
||||
<vbox id="automaticJournalAbbreviations-vbox">
|
||||
<checkbox id="automaticJournalAbbreviations-checkbox" label="&zotero.integration.prefs.automaticJournalAbbeviations.label;"/>
|
||||
<description class="radioDescription">&zotero.integration.prefs.automaticJournalAbbeviations.caption;</description>
|
||||
</vbox>
|
||||
|
||||
<checkbox id="storeReferences" label="&zotero.integration.prefs.storeReferences.label;"/>
|
||||
<description class="radioDescription">&zotero.integration.prefs.storeReferences.caption;</description>
|
||||
</vbox>
|
||||
</dialog>
|
1349
chrome/content/zotero/integration/quickFormat.js
Normal file
120
chrome/content/zotero/integration/quickFormat.xul
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2011 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/integration.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/integration.css" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<window
|
||||
id="quick-format-dialog"
|
||||
orient="vertical"
|
||||
title="&zotero.integration.quickFormatDialog.title;"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
persist="screenX screenY"
|
||||
onkeypress="Zotero_QuickFormat.onKeyPress(event)"
|
||||
onunload="Zotero_QuickFormat.onUnload()">
|
||||
|
||||
<script src="../include.js"/>
|
||||
<script src="windowDraggingUtils.js" type="text/javascript;version=1.8"/>
|
||||
<script src="quickFormat.js" type="text/javascript;version=1.8"/>
|
||||
|
||||
<box orient="horizontal" id="quick-format-entry">
|
||||
<deck id="quick-format-deck" selectedIndex="0" flex="1">
|
||||
<hbox id="quick-format-search" flex="1" align="start">
|
||||
<hbox flex="1">
|
||||
<toolbarbutton id="zotero-icon" type="menu">
|
||||
<menupopup>
|
||||
<menuitem id="keep-sorted" label="&zotero.citation.keepSorted.label;"
|
||||
oncommand="Zotero_QuickFormat.onKeepSortedCommand()" type="checkbox"
|
||||
hidden="true"/>
|
||||
<menuitem id="show-editor" label="&zotero.integration.showEditor.label;"
|
||||
oncommand="Zotero_QuickFormat.onShowEditorCommand()" type="checkbox"
|
||||
hidden="true"/>
|
||||
<menuitem id="classic-view" label="&zotero.integration.classicView.label;"
|
||||
oncommand="Zotero_QuickFormat.onClassicViewCommand()"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
<iframe id="quick-format-iframe" ondragstart="event.stopPropagation()" src="data:application/xhtml+xml,%3C!DOCTYPE%20html%20PUBLIC%20%22-//W3C//DTD%20XHTML%201.0%20Strict//EN%22%20%22http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd%22%3E%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Clink%20rel=%22stylesheet%22%20type=%22text/css%22%20href=%22chrome://zotero/skin/integration.css%22/%3E%3Clink%20rel=%22stylesheet%22%20type=%22text/css%22%20href=%22chrome://zotero-platform/content/integration.css%22/%3E%3C/head%3E%3Cbody%20contenteditable=%22true%22%20spellcheck=%22false%22%20id=%22quick-format-editor%22/%3E%3C/html%3E"
|
||||
tabindex="1" flex="1"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
<progressmeter id="quick-format-progress-meter" mode="undetermined" value="0" flex="1"/>
|
||||
</deck>
|
||||
</box>
|
||||
<panel id="quick-format-reference-panel" noautofocus="true" norestorefocus="true"
|
||||
height="0" width="0">
|
||||
<richlistbox id="quick-format-reference-list" flex="1"/>
|
||||
</panel>
|
||||
<panel id="citation-properties" type="arrow" orient="vertical"
|
||||
onkeypress="Zotero_QuickFormat.onPanelKeyPress(event)"
|
||||
onpopuphidden="Zotero_QuickFormat.onCitationPropertiesClosed(event)">
|
||||
<vbox flex="1">
|
||||
<description id="citation-properties-title"/>
|
||||
<hbox id="citation-properties-info"/>
|
||||
</vbox>
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<menulist id="locator-label" sizetopopup="none"
|
||||
oncommand="Zotero_QuickFormat.onCitationPropertiesChanged(event)">
|
||||
<menupopup id="locator-label-popup"/>
|
||||
</menulist>
|
||||
<textbox id="locator" flex="1"
|
||||
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&zotero.citation.prefix.label;"/>
|
||||
<textbox class="citation-textbox" id="prefix" flex="1"
|
||||
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&zotero.citation.suffix.label;"/>
|
||||
<textbox class="citation-textbox" id="suffix" flex="1"
|
||||
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
|
||||
</row>
|
||||
<html:div>
|
||||
<html:input type="checkbox" id="suppress-author"
|
||||
onchange="Zotero_QuickFormat.onCitationPropertiesChanged(event)"/>
|
||||
<html:label for="suppress-author">
|
||||
&zotero.citation.suppressAuthor.label;
|
||||
</html:label>
|
||||
</html:div>
|
||||
</rows>
|
||||
</grid>
|
||||
<vbox flex="1" align="center">
|
||||
<button id="citation-properties-library-link" onclick="Zotero_QuickFormat.showInLibrary()"/>
|
||||
</vbox>
|
||||
</panel>
|
||||
<zoteroguidancepanel id="quick-format-guidance" about="quickFormat"
|
||||
for="zotero-icon" x="26"/>
|
||||
</window>
|
118
chrome/content/zotero/integration/windowDraggingUtils.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Markus Stange <mstange@themasta.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let EXPORTED_SYMBOLS = [ "WindowDraggingElement" ];
|
||||
|
||||
function WindowDraggingElement(elem, window) {
|
||||
this._elem = elem;
|
||||
this._window = window;
|
||||
this._elem.addEventListener("mousedown", this, false);
|
||||
}
|
||||
|
||||
WindowDraggingElement.prototype = {
|
||||
mouseDownCheck: function(e) { return true; },
|
||||
dragTags: ["box", "hbox", "vbox", "spacer", "label", "statusbarpanel", "stack",
|
||||
"toolbaritem", "toolbarseparator", "toolbarspring", "toolbarspacer",
|
||||
"radiogroup", "deck", "scrollbox", "arrowscrollbox", "tabs"],
|
||||
shouldDrag: function(aEvent) {
|
||||
if (aEvent.button != 0 ||
|
||||
this._window.fullScreen ||
|
||||
!this.mouseDownCheck.call(this._elem, aEvent) ||
|
||||
aEvent.defaultPrevented)
|
||||
return false;
|
||||
|
||||
let target = aEvent.originalTarget, parent = aEvent.originalTarget;
|
||||
|
||||
// The target may be inside an embedded iframe or browser. (bug 615152)
|
||||
if (target.ownerDocument.defaultView != this._window)
|
||||
return false;
|
||||
|
||||
while (parent != this._elem) {
|
||||
let mousethrough = parent.getAttribute("mousethrough");
|
||||
if (mousethrough == "always")
|
||||
target = parent.parentNode;
|
||||
else if (mousethrough == "never")
|
||||
break;
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
while (target != this._elem) {
|
||||
if (this.dragTags.indexOf(target.localName) == -1)
|
||||
return false;
|
||||
target = target.parentNode;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
isPanel : function() {
|
||||
return this._elem instanceof Components.interfaces.nsIDOMXULElement &&
|
||||
this._elem.localName == "panel";
|
||||
},
|
||||
handleEvent: function(aEvent) {
|
||||
let isPanel = this.isPanel();
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "mousedown":
|
||||
if (!this.shouldDrag(aEvent))
|
||||
return;
|
||||
|
||||
if (isPanel) {
|
||||
let screenRect = this._elem.getOuterScreenRect();
|
||||
this._deltaX = aEvent.screenX - screenRect.left;
|
||||
this._deltaY = aEvent.screenY - screenRect.top;
|
||||
}
|
||||
else {
|
||||
this._deltaX = aEvent.screenX - this._window.screenX;
|
||||
this._deltaY = aEvent.screenY - this._window.screenY;
|
||||
}
|
||||
this._draggingWindow = true;
|
||||
this._window.addEventListener("mousemove", this, false);
|
||||
this._window.addEventListener("mouseup", this, false);
|
||||
break;
|
||||
case "mousemove":
|
||||
if (this._draggingWindow) {
|
||||
let toDrag = this.isPanel() ? this._elem : this._window;
|
||||
toDrag.moveTo(aEvent.screenX - this._deltaX, aEvent.screenY - this._deltaY);
|
||||
}
|
||||
break;
|
||||
case "mouseup":
|
||||
if (this._draggingWindow) {
|
||||
this._draggingWindow = false;
|
||||
this._window.removeEventListener("mousemove", this, false);
|
||||
this._window.removeEventListener("mouseup", this, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
186
chrome/content/zotero/itemPane.js
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var ZoteroItemPane = new function() {
|
||||
this.onLoad = onLoad;
|
||||
|
||||
var _lastItem, _itemBox, _notesLabel, _notesButton, _notesList, _tagsBox, _relatedBox;
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
if (!Zotero || !Zotero.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Not in item pane, so skip the introductions
|
||||
if (!document.getElementById('zotero-view-tabbox')) {
|
||||
return;
|
||||
}
|
||||
|
||||
_itemBox = document.getElementById('zotero-editpane-item-box');
|
||||
_notesLabel = document.getElementById('zotero-editpane-notes-label');
|
||||
_notesButton = document.getElementById('zotero-editpane-notes-add');
|
||||
_notesList = document.getElementById('zotero-editpane-dynamic-notes');
|
||||
_tagsBox = document.getElementById('zotero-editpane-tags');
|
||||
_relatedBox = document.getElementById('zotero-editpane-related');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load a top-level item
|
||||
*/
|
||||
this.viewItem = function (item, mode, index) {
|
||||
if (!index) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
Zotero.debug('Viewing item in pane ' + index);
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
var box = _itemBox;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
var box = _tagsBox;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
var box = _relatedBox;
|
||||
break;
|
||||
}
|
||||
|
||||
// Force blur() when clicking off a textbox to another item in middle
|
||||
// pane, since for some reason it's not being called automatically
|
||||
if (_lastItem && _lastItem != item) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
case 2:
|
||||
box.blurOpenField();
|
||||
// DEBUG: Currently broken
|
||||
//box.scrollToTop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_lastItem = item;
|
||||
|
||||
if (index == 1) {
|
||||
var editable = ZoteroPane_Local.canEdit();
|
||||
_notesButton.hidden = !editable;
|
||||
|
||||
while(_notesList.hasChildNodes()) {
|
||||
_notesList.removeChild(_notesList.firstChild);
|
||||
}
|
||||
|
||||
var notes = Zotero.Items.get(item.getNotes());
|
||||
if (notes.length) {
|
||||
for(var i = 0; i < notes.length; i++) {
|
||||
let id = notes[i].id;
|
||||
|
||||
var icon = document.createElement('image');
|
||||
icon.className = "zotero-box-icon";
|
||||
icon.setAttribute('src','chrome://zotero/skin/treeitem-note.png');
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.className = "zotero-box-label";
|
||||
var title = Zotero.Notes.noteToTitle(notes[i].getNote());
|
||||
title = title ? title : Zotero.getString('pane.item.notes.untitled');
|
||||
label.setAttribute('value', title);
|
||||
label.setAttribute('flex','1'); //so that the long names will flex smaller
|
||||
label.setAttribute('crop','end');
|
||||
|
||||
var box = document.createElement('box');
|
||||
box.setAttribute('class','zotero-clicky');
|
||||
box.addEventListener('click', function () { ZoteroPane_Local.selectItem(id); });
|
||||
box.appendChild(icon);
|
||||
box.appendChild(label);
|
||||
|
||||
if (editable) {
|
||||
var removeButton = document.createElement('label');
|
||||
removeButton.setAttribute("value","-");
|
||||
removeButton.setAttribute("class","zotero-clicky zotero-clicky-minus");
|
||||
removeButton.addEventListener('click', function () { ZoteroItemPane.removeNote(id); });
|
||||
}
|
||||
|
||||
var row = document.createElement('row');
|
||||
row.appendChild(box);
|
||||
if (editable) {
|
||||
row.appendChild(removeButton);
|
||||
}
|
||||
|
||||
_notesList.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
_updateNoteCount();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode) {
|
||||
box.mode = mode;
|
||||
}
|
||||
else {
|
||||
box.mode = 'edit';
|
||||
}
|
||||
box.item = item;
|
||||
}
|
||||
|
||||
|
||||
this.addNote = function (popup) {
|
||||
ZoteroPane_Local.newNote(popup, _lastItem.id);
|
||||
}
|
||||
|
||||
|
||||
this.removeNote = function (id) {
|
||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
if (ps.confirm(null, '', Zotero.getString('pane.item.notes.delete.confirm'))) {
|
||||
Zotero.Items.trash(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _updateNoteCount() {
|
||||
var c = _notesList.childNodes.length;
|
||||
|
||||
var str = 'pane.item.notes.count.';
|
||||
switch (c){
|
||||
case 0:
|
||||
str += 'zero';
|
||||
break;
|
||||
case 1:
|
||||
str += 'singular';
|
||||
break;
|
||||
default:
|
||||
str += 'plural';
|
||||
break;
|
||||
}
|
||||
|
||||
_notesLabel.value = Zotero.getString(str, [c]);
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("load", function(e) { ZoteroItemPane.onLoad(e); }, false);
|
121
chrome/content/zotero/itemPane.xul
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<?xml-stylesheet href="chrome://zotero/skin/itemPane.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="include.js"/>
|
||||
<script src="itemPane.js" type="application/javascript;version=1.8"/>
|
||||
|
||||
<vbox id="zotero-item-pane" zotero-persist="width">
|
||||
<!-- Trash -->
|
||||
<vbox id="zotero-item-restore-button-holder">
|
||||
<button id="zotero-item-restore-button" label="&zotero.items.menu.restoreToLibrary;"
|
||||
oncommand="ZoteroPane_Local.restoreSelectedItems()" hidden="true"/>
|
||||
</vbox>
|
||||
|
||||
<!-- Commons -->
|
||||
<button id="zotero-item-show-original" label="Show Original"
|
||||
oncommand="ZoteroPane_Local.showOriginalItem()" hidden="true"/>
|
||||
|
||||
<deck id="zotero-item-pane-content" selectedIndex="0" flex="1">
|
||||
<!-- Center label (for zero or multiple item selection) -->
|
||||
<groupbox id="zotero-item-pane-groupbox" pack="center" align="center">
|
||||
<label id="zotero-item-pane-message"/>
|
||||
</groupbox>
|
||||
|
||||
<!-- Regular item -->
|
||||
<tabbox id="zotero-view-tabbox" flex="1" onselect="if (!ZoteroPane_Local.collectionsView.selection || event.originalTarget.localName != 'tabpanels') { return; }; ZoteroItemPane.viewItem(ZoteroPane_Local.getSelectedItems()[0], ZoteroPane_Local.collectionsView.editable ? 'edit' : 'view', this.selectedIndex)">
|
||||
<tabs>
|
||||
<tab label="&zotero.tabs.info.label;"/>
|
||||
<tab label="&zotero.tabs.notes.label;"/>
|
||||
<tab label="&zotero.tabs.tags.label;"/>
|
||||
<tab label="&zotero.tabs.related.label;"/>
|
||||
</tabs>
|
||||
<tabpanels id="zotero-view-item" flex="1">
|
||||
<tabpanel>
|
||||
<zoteroitembox id="zotero-editpane-item-box" flex="1"/>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel flex="1" orient="vertical">
|
||||
<vbox flex="1" class="zotero-box">
|
||||
<hbox align="center">
|
||||
<label id="zotero-editpane-notes-label"/>
|
||||
<button id="zotero-editpane-notes-add" label="&zotero.item.add;" oncommand="ZoteroItemPane.addNote(event.shiftKey);"/>
|
||||
</hbox>
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column flex="1"/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows id="zotero-editpane-dynamic-notes" flex="1"/>
|
||||
</grid>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel>
|
||||
<tagsbox id="zotero-editpane-tags" flex="1"/>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel>
|
||||
<seealsobox id="zotero-editpane-related" flex="1"/>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
|
||||
<!-- Note item -->
|
||||
<groupbox id="zotero-view-note" flex="1">
|
||||
<zoteronoteeditor id="zotero-note-editor" flex="1" notitle="1" previousfocus="zotero-items-tree"/>
|
||||
<button id="zotero-view-note-button" label="&zotero.notes.separate;" oncommand="ZoteroPane_Local.openNoteWindow(this.getAttribute('noteID')); if(this.hasAttribute('sourceID')) ZoteroPane_Local.selectItem(this.getAttribute('sourceID'));"/>
|
||||
</groupbox>
|
||||
|
||||
<!-- Attachment item -->
|
||||
<groupbox>
|
||||
<zoteroattachmentbox id="zotero-attachment-box" flex="1"/>
|
||||
</groupbox>
|
||||
|
||||
<!-- Duplicate merging -->
|
||||
<vbox id="zotero-duplicates-merge-pane" flex="1">
|
||||
<groupbox>
|
||||
<button id="zotero-duplicates-merge-button" oncommand="Zotero_Duplicates_Pane.merge()"/>
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="zotero-duplicates-merge-version-select">
|
||||
<description>&zotero.duplicatesMerge.versionSelect;</description>
|
||||
<hbox>
|
||||
<listbox id="zotero-duplicates-merge-original-date" onselect="Zotero_Duplicates_Pane.setMaster(this.selectedIndex)" rows="0"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<groupbox flex="1">
|
||||
<description id="zotero-duplicates-merge-field-select">&zotero.duplicatesMerge.fieldSelect;</description>
|
||||
<zoteroitembox id="zotero-duplicates-merge-item-box" flex="1"/>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</deck>
|
||||
</vbox>
|
||||
</overlay>
|
1
chrome/content/zotero/locale/csl
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit ed11f0764934f8bda3b5097feaaf74d43adfd07d
|
277
chrome/content/zotero/locateManager.xul
Normal file
|
@ -0,0 +1,277 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
<!DOCTYPE prefwindow SYSTEM "chrome://zotero/locale/preferences.dtd">
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/preferences.css"?>
|
||||
|
||||
<!--
|
||||
|
||||
To add a new preference:
|
||||
1) Add a new <preference> to <preferences>
|
||||
2) Add a XUL control with a 'preference' attribute
|
||||
3) (Optional) Add additional setup/change logic to preferences.js
|
||||
4) (Optional) To add an observer for a preference change,
|
||||
add an appropriate case in the switch statement
|
||||
in Zotero.Prefs.observe()
|
||||
|
||||
-->
|
||||
<prefwindow id="zotero-locate-manager-prefs" title="&zotero.preferences.title;" onload="refreshLocateEnginesList()"
|
||||
windowtype="zotero:pref" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<prefpane id="zotero-prefpane-locate"
|
||||
label="&zotero.preferences.prefpane.locate;"
|
||||
image="chrome://zotero/skin/prefs-styles.png">
|
||||
<!-- TODO: pic for locate pane -->
|
||||
<!-- TODO: create labels in dtd -->
|
||||
|
||||
<preferences>
|
||||
<preference id="pref-locate-activeEngines" name="extensions.zotero.locate.activeEngines" type="string"/>
|
||||
</preferences>
|
||||
|
||||
<groupbox flex="1">
|
||||
<caption label="&zotero.preferences.locate.locateEngineManager;"/>
|
||||
|
||||
<label id="locateEngineDescription" width="45em" style="font-size: 10px">
|
||||
&zotero.preferences.locate.locateEnginedescription;
|
||||
</label>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox>
|
||||
<tree flex="1" id="locateManager" hidecolumnpicker="true" rows="10"
|
||||
onselect="document.getElementById('locateManager-delete').disabled = undefined"
|
||||
editable="false">
|
||||
<treecols>
|
||||
<treecol type="checkbox" id="locateManager-checkbox" editable="true" flex="0.5"/>
|
||||
<treecol id="locateManager-name" label="&zotero.preferences.locate.name;" flex="1"/>
|
||||
<treecol id="locateManager-description" label="&zotero.preferences.locate.description;" flex="2"/>
|
||||
</treecols>
|
||||
<treechildren id="locateManager-rows"/>
|
||||
</tree>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox align="center">
|
||||
<hbox pack="start" flex="1">
|
||||
<button label="Toggle" onclick="toggleLocateEngines()" flex="1"/>
|
||||
<button id="locateManager-restoreDefaults" label="&zotero.preferences.locate.restoreDefaults;" onclick="restoreDefaultLocateEngines()" flex="1"/>
|
||||
</hbox>
|
||||
<hbox pack="end" flex="2">
|
||||
<button disabled="true" id="locateManager-delete" label="-" onclick="deleteLocateEngine()" flex="0.5"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<label id="addLocateEngineDescription" style="font-size: 10px; width: 45em; height: 6em">
|
||||
&zotero.preferences.locate.addDescription;
|
||||
</label>
|
||||
</groupbox>
|
||||
</prefpane>
|
||||
|
||||
<script src="chrome://zotero/content/include.js"></script>
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function treeClick(event) {
|
||||
// We only care about primary button double and triple clicks
|
||||
if (!event || (event.detail != 2 && event.detail != 3) || event.button != 0) {
|
||||
return;
|
||||
}
|
||||
var t = event.originalTarget;
|
||||
|
||||
if (t.localName != 'treechildren') {
|
||||
return;
|
||||
}
|
||||
|
||||
var tree = t.parentNode;
|
||||
|
||||
var row = {}, col = {}, obj = {};
|
||||
var cell = tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, obj);
|
||||
|
||||
var treechildren = document.getElementById('locateManager-rows');
|
||||
var treeitem = treechildren.children[row.value];
|
||||
|
||||
treeitem.engine.hidden = !treeitem.engine.hidden;
|
||||
|
||||
refreshLocateEnginesList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the list of locate engines in the locate pane
|
||||
* @param {String} name of locate engine to select
|
||||
*/
|
||||
function refreshLocateEnginesList() {
|
||||
var tree = document.getElementById('locateManager');
|
||||
var treechildren = document.getElementById('locateManager-rows');
|
||||
|
||||
// add click listener
|
||||
tree.addEventListener("click", treeClick, false);
|
||||
|
||||
// store ranges
|
||||
var nRanges = tree.view.selection.getRangeCount();
|
||||
var start = {};
|
||||
var end = {};
|
||||
var ranges = [];
|
||||
for(var i=0; i<nRanges; i++) {
|
||||
tree.view.selection.getRangeAt(i, start, end);
|
||||
ranges.push([start.value, end.value]);
|
||||
}
|
||||
|
||||
// clear tree
|
||||
while (treechildren.hasChildNodes()) {
|
||||
treechildren.removeChild(treechildren.firstChild);
|
||||
}
|
||||
|
||||
// repopulate tree with available engines
|
||||
var engines = Zotero.LocateManager.getEngines();
|
||||
var i = 0;
|
||||
for each(var engine in engines) {
|
||||
var treeitem = document.createElement('treeitem');
|
||||
var treerow = document.createElement('treerow');
|
||||
var checkboxCell = document.createElement('treecell');
|
||||
var nameCell = document.createElement('treecell');
|
||||
var descriptionCell = document.createElement('treecell');
|
||||
|
||||
treeitem.engine = engine;
|
||||
nameCell.setAttribute('label', engine.name);
|
||||
descriptionCell.setAttribute('label', engine.description);
|
||||
if( !engine.hidden ) {
|
||||
checkboxCell.setAttribute('value', 'true');
|
||||
}
|
||||
|
||||
treerow.appendChild(checkboxCell);
|
||||
treerow.appendChild(nameCell);
|
||||
treerow.appendChild(descriptionCell);
|
||||
treeitem.appendChild(treerow);
|
||||
treechildren.appendChild(treeitem);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// restore ranges
|
||||
for each(var range in ranges) {
|
||||
if(range[1] <= engines.length-1) {
|
||||
tree.view.selection.rangedSelect(range[0], range[1], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new Locate Engine to the locate pane
|
||||
**/
|
||||
/*
|
||||
function addLocateEngine() {
|
||||
// alert(Zotero.LocateManager.activeLocateEngines.join(" || "));
|
||||
var textbox = document.getElementById('locate-add-textbox');
|
||||
Zotero.LocateManager.addLocateEngine(textbox.value);
|
||||
|
||||
refreshLocateEnginesList();
|
||||
}
|
||||
*/
|
||||
|
||||
function toggleLocateEngines() {
|
||||
// get selected engines names
|
||||
var tree = document.getElementById('locateManager');
|
||||
var treeItems = tree.lastChild.childNodes;
|
||||
var engineNames = [];
|
||||
var start = {};
|
||||
var end = {};
|
||||
var nRanges = tree.view.selection.getRangeCount();
|
||||
var numStatuses = 0;
|
||||
var engineStatusesSum = 0;
|
||||
for(var i=0; i<nRanges; i++) {
|
||||
tree.view.selection.getRangeAt(i, start, end);
|
||||
for(var j=start.value; j<=end.value; j++) {
|
||||
var engineStatus = treeItems[j].engine.hidden ? 0 : 1;
|
||||
numStatuses += 1;
|
||||
engineStatusesSum += engineStatus;
|
||||
}
|
||||
}
|
||||
|
||||
var hidden;
|
||||
switch( engineStatusesSum ) {
|
||||
case 0:
|
||||
// all off, turn all on
|
||||
hidden = false;
|
||||
break;
|
||||
|
||||
case numStatuses:
|
||||
// all on, turn all off
|
||||
hidden = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// some on, some off. turn all on
|
||||
hidden = false;
|
||||
}
|
||||
|
||||
Zotero.LocateManager.getEngines().forEach(engine => engine.hidden = hidden);
|
||||
|
||||
refreshLocateEnginesList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes selected Locate Engines from the locate pane
|
||||
**/
|
||||
function deleteLocateEngine() {
|
||||
// get selected engines names
|
||||
var tree = document.getElementById('locateManager');
|
||||
var treeItems = tree.lastChild.childNodes;
|
||||
var engineNames = [];
|
||||
var start = {};
|
||||
var end = {};
|
||||
var nRanges = tree.view.selection.getRangeCount();
|
||||
for(var i=0; i<nRanges; i++) {
|
||||
tree.view.selection.getRangeAt(i, start, end);
|
||||
for(var j=start.value; j<=end.value; j++) {
|
||||
Zotero.LocateManager.removeEngine(treeItems[j].engine);
|
||||
}
|
||||
}
|
||||
|
||||
for(var i=0; i<engineNames.length; i++) {
|
||||
Zotero.LocateManager.removeLocateEngine(engineNames[i]);
|
||||
}
|
||||
|
||||
tree.view.selection.clearSelection();
|
||||
refreshLocateEnginesList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores Default Locate Engines
|
||||
**/
|
||||
function restoreDefaultLocateEngines() {
|
||||
Zotero.LocateManager.restoreDefaultEngines();
|
||||
refreshLocateEnginesList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</prefwindow>
|
578
chrome/content/zotero/locateMenu.js
Normal file
|
@ -0,0 +1,578 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
/*
|
||||
* This object contains the various functions for the interface
|
||||
*/
|
||||
var Zotero_LocateMenu = new function() {
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ios", "@mozilla.org/network/io-service;1", "nsIIOService");
|
||||
|
||||
/**
|
||||
* Clear and build the locate menu
|
||||
*/
|
||||
this.buildLocateMenu = function() {
|
||||
var locateMenu = document.getElementById('zotero-tb-locate-menu');
|
||||
|
||||
// clear menu
|
||||
while(locateMenu.childElementCount > 0) {
|
||||
locateMenu.removeChild(locateMenu.firstChild);
|
||||
}
|
||||
|
||||
var selectedItems = _getSelectedItems();
|
||||
|
||||
if(selectedItems.length) {
|
||||
_addViewOptions(locateMenu, selectedItems, true, true);
|
||||
|
||||
var availableEngines = _getAvailableLocateEngines(selectedItems);
|
||||
// add engines that are available for selected items
|
||||
if(availableEngines.length) {
|
||||
Zotero_LocateMenu.addLocateEngines(locateMenu, availableEngines, null, true);
|
||||
}
|
||||
} else {
|
||||
// add "no items selected"
|
||||
menuitem = _createMenuItem(Zotero.getString("pane.item.selected.zero"), "no-items-selected");
|
||||
locateMenu.appendChild(menuitem);
|
||||
menuitem.disabled = true;
|
||||
}
|
||||
|
||||
// add separator at end if necessary
|
||||
if(locateMenu.lastChild.tagName !== "menuseparator") {
|
||||
locateMenu.appendChild(document.createElement("menuseparator"));
|
||||
}
|
||||
|
||||
// add installable locate menus, if there are any
|
||||
if(window.Zotero_Browser) {
|
||||
var installableLocateEngines = _getInstallableLocateEngines();
|
||||
} else {
|
||||
var installableLocateEngines = [];
|
||||
}
|
||||
|
||||
if(installableLocateEngines.length) {
|
||||
for (let locateEngine of installableLocateEngines) {
|
||||
var menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("label", locateEngine.label);
|
||||
menuitem.setAttribute("class", "menuitem-iconic");
|
||||
menuitem.setAttribute("image", locateEngine.image);
|
||||
menuitem.zoteroLocateInfo = locateEngine;
|
||||
menuitem.addEventListener("command", _addLocateEngine, false);
|
||||
|
||||
locateMenu.appendChild(menuitem);
|
||||
}
|
||||
}
|
||||
|
||||
var menuitem = document.createElement("menuitem");
|
||||
menuitem = _createMenuItem(Zotero.getString("locate.manageLocateEngines"), "zotero-manage-locate-menu");
|
||||
menuitem.addEventListener("command", _openLocateEngineManager, false);
|
||||
locateMenu.appendChild(menuitem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the bottom part of the context menu and add locate options
|
||||
* @param {menupopup} menu The menu to add context menu items to
|
||||
* @param {Boolean} showIcons Whether menu items should have associated icons
|
||||
*/
|
||||
this.buildContextMenu = function(menu, showIcons) {
|
||||
// get selected items
|
||||
var selectedItems = _getSelectedItems();
|
||||
|
||||
// if no items selected or >20 items selected, stop now
|
||||
if(!selectedItems.length || selectedItems.length > 20) return;
|
||||
|
||||
// add view options
|
||||
_addViewOptions(menu, selectedItems, showIcons);
|
||||
|
||||
/*// look for locate engines
|
||||
var availableEngines = _getAvailableLocateEngines(selectedItems);
|
||||
if(availableEngines.length) {
|
||||
// if locate engines are available, make a new submenu
|
||||
var submenu = document.createElement("menu");
|
||||
submenu.setAttribute("zotero-locate", "true");
|
||||
submenu.setAttribute("label", Zotero.getString("locate.locateEngines"));
|
||||
|
||||
// add locate engines to the submenu
|
||||
_addLocateEngines(submenuPopup, availableEngines, true);
|
||||
|
||||
submenu.appendChild(submenuPopup);
|
||||
menu.appendChild(submenu);
|
||||
}*/
|
||||
}
|
||||
|
||||
function _addViewOption(selectedItems, optionName, optionObject, showIcons) {
|
||||
var menuitem = _createMenuItem(Zotero.getString("locate."+optionName+".label"),
|
||||
null, Zotero.getString("locate."+optionName+".tooltip"));
|
||||
if(showIcons) {
|
||||
menuitem.setAttribute("class", "menuitem-iconic");
|
||||
menuitem.style.listStyleImage = "url('"+optionObject.icon+"')";
|
||||
}
|
||||
menuitem.setAttribute("zotero-locate", "true");
|
||||
|
||||
menuitem.addEventListener("command", function(event) {
|
||||
optionObject.handleItems(selectedItems, event);
|
||||
}, false)
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add view options to a menu
|
||||
* @param {menupopup} locateMenu The menu to add menu items to
|
||||
* @param {Zotero.Item[]} selectedItems The items to create view options based upon
|
||||
* @param {Boolean} showIcons Whether menu items should have associated icons
|
||||
* @param {Boolean} addExtraOptions Whether to add options that start with "_" below the separator
|
||||
*/
|
||||
function _addViewOptions(locateMenu, selectedItems, showIcons, addExtraOptions) {
|
||||
var optionsToShow = {};
|
||||
|
||||
// check which view options are available
|
||||
for (let item of selectedItems) {
|
||||
for(var viewOption in ViewOptions) {
|
||||
if(!optionsToShow[viewOption]) {
|
||||
optionsToShow[viewOption] = ViewOptions[viewOption].canHandleItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add available view options to menu
|
||||
var lastNode = locateMenu.hasChildNodes() ? locateMenu.firstChild : null;
|
||||
var haveOptions = false;
|
||||
for(var viewOption in optionsToShow) {
|
||||
if(viewOption[0] === "_" || !optionsToShow[viewOption]) continue;
|
||||
locateMenu.insertBefore(_addViewOption(selectedItems, viewOption,
|
||||
ViewOptions[viewOption], showIcons), lastNode);
|
||||
haveOptions = true;
|
||||
}
|
||||
|
||||
if(haveOptions) {
|
||||
var sep = document.createElement("menuseparator");
|
||||
sep.setAttribute("zotero-locate", "true");
|
||||
locateMenu.insertBefore(sep, lastNode);
|
||||
}
|
||||
|
||||
if(addExtraOptions) {
|
||||
for (let viewOption in optionsToShow) {
|
||||
if(viewOption[0] !== "_" || !optionsToShow[viewOption]) continue;
|
||||
locateMenu.insertBefore(_addViewOption(selectedItems, viewOption.substr(1),
|
||||
ViewOptions[viewOption], showIcons), lastNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available locate engines that can handle a set of items
|
||||
* @param {Zotero.Item[]} selectedItems The items to look or locate engines for
|
||||
* @return {Zotero.LocateManater.LocateEngine[]} An array of locate engines capable of handling
|
||||
* the given items
|
||||
*/
|
||||
function _getAvailableLocateEngines(selectedItems) {
|
||||
// check for custom locate engines
|
||||
var customEngines = Zotero.LocateManager.getVisibleEngines();
|
||||
var availableEngines = [];
|
||||
|
||||
// check which engines can translate an item
|
||||
for (let engine of customEngines) {
|
||||
// require a submission for at least one selected item
|
||||
for (let item of selectedItems) {
|
||||
if(engine.getItemSubmission(item)) {
|
||||
availableEngines.push(engine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return availableEngines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add locate engine options to a menu
|
||||
* @param {menupopup} menu The menu to add menu items to
|
||||
* @param {Zotero.LocateManager.LocateEngine[]} engines The list of engines to add to the menu
|
||||
* @param {Function|null} items Function to call to locate items
|
||||
* @param {Boolean} showIcons Whether menu items should have associated icons
|
||||
*/
|
||||
this.addLocateEngines = function(menu, engines, locateFn, showIcons) {
|
||||
if(!locateFn) {
|
||||
locateFn = this.locateItem;
|
||||
}
|
||||
|
||||
for (let engine of engines) {
|
||||
var menuitem = _createMenuItem(engine.name, null, engine.description);
|
||||
menuitem.setAttribute("class", "menuitem-iconic");
|
||||
menuitem.setAttribute("image", engine.icon);
|
||||
menu.appendChild(menuitem);
|
||||
menuitem.addEventListener("command", locateFn, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new menuitem XUL element
|
||||
*/
|
||||
function _createMenuItem( label, id, tooltiptext ) {
|
||||
var menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("label", label);
|
||||
if(id) menuitem.setAttribute("id", id);
|
||||
if(tooltiptext) menuitem.setAttribute("tooltiptext", tooltiptext);
|
||||
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any locate engines that can be installed from the current page
|
||||
*/
|
||||
function _getInstallableLocateEngines() {
|
||||
var locateEngines = [];
|
||||
if(!window.Zotero_Browser || !window.Zotero_Browser.tabbrowser) return locateEngines;
|
||||
|
||||
var links = Zotero_Browser.tabbrowser.selectedBrowser.contentDocument.getElementsByTagName("link");
|
||||
for (let link of links) {
|
||||
if(!link.getAttribute) continue;
|
||||
var rel = link.getAttribute("rel");
|
||||
if(rel && rel === "search") {
|
||||
var type = link.getAttribute("type");
|
||||
if(type && type === "application/x-openurl-opensearchdescription+xml") {
|
||||
var label = link.getAttribute("title");
|
||||
if(label) {
|
||||
if(Zotero.LocateManager.getEngineByName(label)) {
|
||||
label = 'Update "'+label+'"';
|
||||
} else {
|
||||
label = 'Add "'+label+'"';
|
||||
}
|
||||
} else {
|
||||
label = 'Add Locate Engine';
|
||||
}
|
||||
|
||||
locateEngines.push({'label':label,
|
||||
'href':link.getAttribute("href"),
|
||||
'image':Zotero_Browser.tabbrowser.selectedTab.image});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return locateEngines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate selected items
|
||||
*/
|
||||
this.locateItem = function(event, selectedItems) {
|
||||
if(!selectedItems) {
|
||||
selectedItems = _getSelectedItems();
|
||||
}
|
||||
|
||||
// find selected engine
|
||||
var selectedEngine = Zotero.LocateManager.getEngineByName(event.target.label);
|
||||
if(!selectedEngine) throw "Selected locate engine not found";
|
||||
|
||||
var urls = [];
|
||||
var postDatas = [];
|
||||
for (let item of selectedItems) {
|
||||
var submission = selectedEngine.getItemSubmission(item);
|
||||
if(submission) {
|
||||
urls.push(submission.uri.spec);
|
||||
postDatas.push(submission.postData);
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.debug("Loading using "+selectedEngine.name);
|
||||
Zotero.debug(urls);
|
||||
ZoteroPane_Local.loadURI(urls, event, postDatas);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new locate engine
|
||||
*/
|
||||
function _addLocateEngine(event) {
|
||||
Zotero.LocateManager.addEngine(event.target.zoteroLocateInfo.href,
|
||||
Components.interfaces.nsISearchEngine.TYPE_OPENSEARCH,
|
||||
event.target.zoteroLocateInfo.image, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the locate manager
|
||||
*/
|
||||
function _openLocateEngineManager(event) {
|
||||
window.openDialog('chrome://zotero/content/locateManager.xul',
|
||||
'Zotero Locate Engine Manager',
|
||||
'chrome,centerscreen'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first 50 selected items
|
||||
*/
|
||||
function _getSelectedItems() {
|
||||
var allSelectedItems = ZoteroPane_Local.getSelectedItems();
|
||||
var selectedItems = [];
|
||||
while(selectedItems.length < 50 && allSelectedItems.length) {
|
||||
var item = allSelectedItems.shift();
|
||||
if(!item.isNote()) selectedItems.push(item);
|
||||
}
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
var ViewOptions = {};
|
||||
|
||||
/**
|
||||
* "View PDF" option
|
||||
*
|
||||
* Should appear only when the item is a PDF, or a linked or attached file or web attachment is
|
||||
* a PDF
|
||||
*/
|
||||
ViewOptions.pdf = new function() {
|
||||
this.icon = "chrome://zotero/skin/treeitem-attachment-pdf.png";
|
||||
this._mimeTypes = ["application/pdf"];
|
||||
this.canHandleItem = function(item) !!_getFirstAttachmentWithMIMEType(item, this._mimeTypes);
|
||||
|
||||
this.handleItems = function(items, event) {
|
||||
var attachments = [];
|
||||
for (let item of items) {
|
||||
var attachment = _getFirstAttachmentWithMIMEType(item, this._mimeTypes);
|
||||
if(attachment) attachments.push(attachment.id);
|
||||
}
|
||||
|
||||
ZoteroPane_Local.viewAttachment(attachments, event);
|
||||
}
|
||||
|
||||
function _getFirstAttachmentWithMIMEType(item, mimeTypes) {
|
||||
var attachments = (item.isAttachment() ? [item] : Zotero.Items.get(item.getBestAttachments()));
|
||||
for (let i = 0; i < attachments.length; i++) {
|
||||
let attachment = attachments[i];
|
||||
if (mimeTypes.indexOf(attachment.attachmentMIMEType) !== -1
|
||||
&& attachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL) {
|
||||
return attachment;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* "View Online" option
|
||||
*
|
||||
* Should appear only when an item or an attachment has a URL
|
||||
*/
|
||||
ViewOptions.online = new function() {
|
||||
this.icon = "chrome://zotero/skin/locate-view-online.png";
|
||||
this.canHandleItem = function(item) _getURL(item) !== false;
|
||||
|
||||
this.handleItems = function(items, event) {
|
||||
var urls = [for (item of items) _getURL(item)];
|
||||
ZoteroPane_Local.loadURI([for (url of urls) if (url) url], event);
|
||||
}
|
||||
|
||||
function _getURL(item) {
|
||||
// try url field for item and for attachments
|
||||
var urlField = item.getField('url');
|
||||
if(urlField) {
|
||||
var uri;
|
||||
try {
|
||||
uri = Zotero_LocateMenu.ios.newURI(urlField, null, null);
|
||||
if(uri && uri.host && uri.scheme !== 'file') return urlField;
|
||||
} catch(e) {};
|
||||
}
|
||||
|
||||
if(item.isRegularItem()) {
|
||||
var attachments = item.getAttachments();
|
||||
if(attachments) {
|
||||
// look through url fields for non-file:/// attachments
|
||||
for (let attachment of Zotero.Items.get(attachments)) {
|
||||
var urlField = attachment.getField('url');
|
||||
if(urlField) return urlField;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if no url field, try DOI field
|
||||
var doi = item.getField('DOI');
|
||||
if(doi && typeof doi === "string") {
|
||||
doi = Zotero.Utilities.cleanDOI(doi);
|
||||
if(doi) {
|
||||
return "http://dx.doi.org/" + encodeURIComponent(doi);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* "View Snapshot" option
|
||||
*
|
||||
* Should appear only when the item is a PDF, or a linked or attached file or web attachment is
|
||||
* a snapshot
|
||||
*/
|
||||
ViewOptions.snapshot = new function() {
|
||||
this.icon = "chrome://zotero/skin/treeitem-attachment-snapshot.png";
|
||||
this._mimeTypes = ["text/html", "application/xhtml+xml"];
|
||||
this.canHandleItem = ViewOptions.pdf.canHandleItem;
|
||||
this.handleItems = ViewOptions.pdf.handleItems;
|
||||
};
|
||||
|
||||
/**
|
||||
* "View File" option
|
||||
*
|
||||
* Should appear only when an item or a linked or attached file or web attachment does not
|
||||
* satisfy the conditions for "View PDF" or "View Snapshot"
|
||||
*/
|
||||
ViewOptions.file = new function() {
|
||||
this.icon = "chrome://zotero/skin/treeitem-attachment-file.png";
|
||||
this.canHandleItem = function(item) !!_getFile(item);
|
||||
|
||||
this.handleItems = function(items, event) {
|
||||
var attachments = [];
|
||||
for (let item of items) {
|
||||
var attachment = _getFile(item);
|
||||
if(attachment) attachments.push(attachment.id);
|
||||
}
|
||||
|
||||
ZoteroPane_Local.viewAttachment(attachments, event);
|
||||
}
|
||||
|
||||
function _getFile(item) {
|
||||
var attachments = (item.isAttachment() ? [item] : Zotero.Items.get(item.getBestAttachments()));
|
||||
for (let i = 0; i < attachments.length; i++) {
|
||||
let attachment = attachments[i];
|
||||
if(!ViewOptions.snapshot.canHandleItem(attachment)
|
||||
&& !ViewOptions.pdf.canHandleItem(attachment)
|
||||
&& attachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL) {
|
||||
return attachment;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* "Open in External Viewer" option
|
||||
*
|
||||
* Should appear only when an item or a linked or attached file or web attachment can be
|
||||
* viewed by an internal non-native handler and "launchNonNativeFiles" pref is disabled
|
||||
*/
|
||||
ViewOptions.externalViewer = new function() {
|
||||
this.icon = "chrome://zotero/skin/locate-external-viewer.png";
|
||||
this.useExternalViewer = true;
|
||||
|
||||
this.canHandleItem = function(item) {
|
||||
return (this.useExternalViewer ^ Zotero.Prefs.get('launchNonNativeFiles'))
|
||||
&& _getBestNonNativeAttachment(item);
|
||||
}
|
||||
|
||||
this.handleItems = function(items, event) {
|
||||
var attachments = [];
|
||||
for (let item of items) {
|
||||
var attachment = _getBestNonNativeAttachment(item);
|
||||
if(attachment) attachments.push(attachment.id);
|
||||
}
|
||||
|
||||
ZoteroPane_Local.viewAttachment(attachments, event, false, this.useExternalViewer);
|
||||
}
|
||||
|
||||
function _getBestNonNativeAttachment(item) {
|
||||
var attachments = (item.isAttachment() ? [item] : Zotero.Items.get(item.getBestAttachments()));
|
||||
for (let i = 0; i < attachments.length; i++) {
|
||||
let attachment = attachments[i];
|
||||
if(attachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL) {
|
||||
var file = attachment.getFile();
|
||||
if(file) {
|
||||
var ext = Zotero.File.getExtension(file);
|
||||
if(!attachment.attachmentMIMEType ||
|
||||
Zotero.MIME.hasNativeHandler(attachment.attachmentMIMEType, ext) ||
|
||||
!Zotero.MIME.hasInternalHandler(attachment.attachmentMIMEType, ext)) {
|
||||
return false;
|
||||
}
|
||||
return attachment;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* "Open in Internal Viewer" option
|
||||
*
|
||||
* Should appear only when an item or a linked or attached file or web attachment can be
|
||||
* viewed by an internal non-native handler and "launchNonNativeFiles" pref is enabled
|
||||
*/
|
||||
ViewOptions.internalViewer = new function() {
|
||||
this.icon = "chrome://zotero/skin/locate-internal-viewer.png";
|
||||
this.useExternalViewer = false;
|
||||
this.canHandleItem = ViewOptions.externalViewer.canHandleItem;
|
||||
this.handleItems = ViewOptions.externalViewer.handleItems;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Show File" option
|
||||
*
|
||||
* Should appear only when an item is a file or web attachment, or has a linked or attached
|
||||
* file or web attachment
|
||||
*/
|
||||
ViewOptions.showFile = new function() {
|
||||
this.icon = "chrome://zotero/skin/locate-show-file.png";
|
||||
this.useExternalViewer = true;
|
||||
|
||||
this.canHandleItem = function(item) {
|
||||
return !!_getBestFile(item);
|
||||
}
|
||||
|
||||
this.handleItems = function(items, event) {
|
||||
for (let item of items) {
|
||||
var attachment = _getBestFile(item);
|
||||
if(attachment) {
|
||||
ZoteroPane_Local.showAttachmentInFilesystem(attachment.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _getBestFile(item) {
|
||||
if(item.isAttachment()) {
|
||||
if(item.attachmentLinkMode === Zotero.Attachments.LINK_MODE_LINKED_URL) return false;
|
||||
return item;
|
||||
} else {
|
||||
return Zotero.Items.get(item.getBestAttachment());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* "Library Lookup" Option
|
||||
*
|
||||
* Should appear only for regular items
|
||||
*/
|
||||
ViewOptions._libraryLookup = new function() {
|
||||
this.icon = "chrome://zotero/skin/locate-library-lookup.png";
|
||||
this.canHandleItem = function(item) item.isRegularItem();
|
||||
this.handleItems = function(items, event) {
|
||||
var urls = [];
|
||||
for (let item of items) {
|
||||
if(!item.isRegularItem()) continue;
|
||||
var url = Zotero.OpenURL.resolve(item);
|
||||
if(url) urls.push(url);
|
||||
}
|
||||
ZoteroPane_Local.loadURI(urls, event);
|
||||
}
|
||||
};
|
||||
}
|
217
chrome/content/zotero/longTagFixer.js
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
var Zotero_Long_Tag_Fixer = new function () {
|
||||
var _oldTag = window.arguments[0];
|
||||
var _dataOut = window.arguments[1];
|
||||
|
||||
this.init = function () {
|
||||
document.getElementById('zotero-old-tag').value = _oldTag;
|
||||
document.getElementById('zotero-old-tag-delimiter').nextSibling.value = Zotero.getString('general.character.singular');
|
||||
|
||||
var delimiter = Zotero.Prefs.get('lastLongTagDelimiter');
|
||||
document.getElementById('zotero-old-tag-delimiter').value = delimiter;
|
||||
|
||||
var lastMode = Zotero.Prefs.get('lastLongTagMode');
|
||||
if (!lastMode) {
|
||||
lastMode = 0;
|
||||
}
|
||||
this.switchMode(lastMode);
|
||||
}
|
||||
|
||||
this.switchMode = function (index) {
|
||||
var dialog = document.getElementById('zotero-long-tag-fixer');
|
||||
|
||||
document.getElementById('zotero-new-tag-actions').selectedIndex = index;
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
var buttonLabel = "saveTags";
|
||||
this.updateTagList();
|
||||
document.getElementById('zotero-old-tag-delimiter').select();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
var buttonLabel = "saveTag";
|
||||
document.getElementById('zotero-new-tag-editor').value = _oldTag;
|
||||
this.updateEditLength(_oldTag.length)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
var buttonLabel = "deleteTag";
|
||||
dialog.getButton('accept').disabled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
document.getElementById('zotero-long-tag-fixer').getButton('accept').label = Zotero.getString('sync.longTagFixer.' + buttonLabel);
|
||||
window.sizeToContent();
|
||||
Zotero.Prefs.set('lastLongTagMode', index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Split tags and populate list
|
||||
*/
|
||||
this.updateTagList = function () {
|
||||
var listbox = document.getElementById('zotero-new-tag-list');
|
||||
while (listbox.childNodes.length) {
|
||||
listbox.removeChild(listbox.lastChild);
|
||||
}
|
||||
|
||||
var delimiter = document.getElementById('zotero-old-tag-delimiter').value;
|
||||
if (delimiter) {
|
||||
Zotero.Prefs.set('lastLongTagDelimiter', delimiter);
|
||||
var re = new RegExp("\\s*" + delimiter.replace(/([\.\-\[\]\(\)\?\*\+])/g, "\\$1") + "\\s*");
|
||||
var tags = _oldTag.split(re);
|
||||
}
|
||||
|
||||
var acceptButton = document.getElementById('zotero-long-tag-fixer').getButton('accept');
|
||||
if (!delimiter || tags.length < 2) {
|
||||
acceptButton.disabled = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
acceptButton.disabled = false;
|
||||
}
|
||||
|
||||
tags.sort();
|
||||
for (var i=0; i<tags.length; i++) {
|
||||
if (i != 0 && tags[i] == tags[i-1]) {
|
||||
continue;
|
||||
}
|
||||
if (!tags[i]) {
|
||||
continue;
|
||||
}
|
||||
var li = listbox.appendItem(tags[i]);
|
||||
li.setAttribute('type', 'checkbox');
|
||||
li.setAttribute('checked', 'true');
|
||||
}
|
||||
|
||||
window.sizeToContent();
|
||||
}
|
||||
|
||||
|
||||
this.deselectAll = function () {
|
||||
var lis = document.getElementById('zotero-new-tag-list').getElementsByTagName('listitem');
|
||||
for (var i=0; i<lis.length; i++) {
|
||||
lis[i].checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.selectAll = function () {
|
||||
var lis = document.getElementById('zotero-new-tag-list').getElementsByTagName('listitem');
|
||||
for (var i=0; i<lis.length; i++) {
|
||||
lis[i].checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.updateEditLength = function (len) {
|
||||
document.getElementById('zotero-new-tag-character-count').value = len;
|
||||
var invalid = len == 0 || len > 255;
|
||||
document.getElementById('zotero-new-tag-characters').setAttribute('invalid', invalid);
|
||||
document.getElementById('zotero-long-tag-fixer').getButton('accept').disabled = invalid;
|
||||
}
|
||||
|
||||
|
||||
this.cancel = function () {
|
||||
_dataOut.result = false;
|
||||
}
|
||||
|
||||
|
||||
this.save = function () {
|
||||
try {
|
||||
|
||||
var index = document.getElementById('zotero-new-tag-actions').selectedIndex;
|
||||
|
||||
// Search for all matching tags across all libraries
|
||||
var sql = "SELECT tagID FROM tags WHERE name=?";
|
||||
var oldTagIDs = Zotero.DB.columnQuery(sql, _oldTag);
|
||||
|
||||
switch (index) {
|
||||
// Split
|
||||
case 0:
|
||||
// Get checked tags
|
||||
var listbox = document.getElementById('zotero-new-tag-list');
|
||||
var len = listbox.childElementCount;
|
||||
var newTags = [];
|
||||
for (var i=0; i<len; i++) {
|
||||
var li = listbox.childNodes[i];
|
||||
if (li.getAttribute('checked') == 'true') {
|
||||
newTags.push(li.getAttribute('label'));
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.DB.beginTransaction();
|
||||
|
||||
// Add new tags to all items linked to each matching old tag
|
||||
for (var i=0; i<oldTagIDs.length; i++) {
|
||||
var tag = Zotero.Tags.get(oldTagIDs[i]);
|
||||
var items = tag.getLinkedItems();
|
||||
if (items) {
|
||||
for (var j=0; j<items.length; j++) {
|
||||
items[j].addTags(newTags, tag.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old tags
|
||||
Zotero.Tags.erase(oldTagIDs);
|
||||
Zotero.Tags.purge();
|
||||
Zotero.DB.commitTransaction();
|
||||
break;
|
||||
|
||||
// Edit
|
||||
case 1:
|
||||
var value = document.getElementById('zotero-new-tag-editor').value;
|
||||
Zotero.DB.beginTransaction();
|
||||
for (var i=0; i<oldTagIDs.length; i++) {
|
||||
var tag = Zotero.Tags.get(oldTagIDs[i]);
|
||||
tag.name = value;
|
||||
tag.save();
|
||||
}
|
||||
Zotero.DB.commitTransaction();
|
||||
break;
|
||||
|
||||
// Delete
|
||||
case 2:
|
||||
Zotero.DB.beginTransaction();
|
||||
Zotero.Tags.erase(oldTagIDs);
|
||||
Zotero.Tags.purge();
|
||||
Zotero.DB.commitTransaction();
|
||||
break;
|
||||
}
|
||||
|
||||
_dataOut.result = true;
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
}
|
74
chrome/content/zotero/longTagFixer.xul
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/longTagFixer.css" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<dialog id="zotero-long-tag-fixer" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
buttons="accept,cancel"
|
||||
onload="Zotero_Long_Tag_Fixer.init()"
|
||||
ondialogcancel="Zotero_Long_Tag_Fixer.cancel()"
|
||||
ondialogaccept="Zotero_Long_Tag_Fixer.save()"
|
||||
title="&zotero.sync.error;">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="longTagFixer.js"/>
|
||||
|
||||
<label value="&zotero.sync.longTagFixer.followingTagTooLong;"/>
|
||||
<groupbox>
|
||||
<textbox id="zotero-old-tag" multiline="true" rows="4" readonly="true" class="plain"/>
|
||||
</groupbox>
|
||||
<label>&zotero.sync.longTagFixer.syncedTagSizeLimit;</label>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<label value="&zotero.sync.longTagFixer.splitEditDelete;"/>
|
||||
|
||||
<separator/>
|
||||
|
||||
<tabbox id="zotero-new-tag-actions">
|
||||
<tabs oncommand="Zotero_Long_Tag_Fixer.switchMode(this.selectedIndex)">
|
||||
<tab label="&zotero.sync.longTagFixer.split;"/>
|
||||
<tab label="&zotero.general.edit;"/>
|
||||
<tab label="&zotero.general.delete;"/>
|
||||
</tabs>
|
||||
<tabpanels>
|
||||
<!-- Split -->
|
||||
<vbox>
|
||||
<hbox align="center">
|
||||
<label>&zotero.sync.longTagFixer.splitAtThe;</label>
|
||||
<textbox id="zotero-old-tag-delimiter" size="1"
|
||||
oninput="this.nextSibling.value = Zotero.getString('general.character.' + (this.value.length > 1 ? 'plural' : 'singular')); Zotero_Long_Tag_Fixer.updateTagList();"/>
|
||||
<label/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<listbox id="zotero-new-tag-list" rows="8"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<label value="&zotero.sync.longTagFixer.uncheckedTagsNotSaved;"/>
|
||||
|
||||
<hbox>
|
||||
<button label="&zotero.general.deselectAll;" oncommand="Zotero_Long_Tag_Fixer.deselectAll()"/>
|
||||
<button label="&zotero.general.selectAll;" oncommand="Zotero_Long_Tag_Fixer.selectAll()"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<!-- Edit -->
|
||||
<vbox>
|
||||
<textbox id="zotero-new-tag-editor" multiline="true" flex="1"
|
||||
oninput="Zotero_Long_Tag_Fixer.updateEditLength(this.value.length)"/>
|
||||
<hbox id="zotero-new-tag-characters">
|
||||
<label id="zotero-new-tag-character-count"/>
|
||||
<label value="&zotero.sync.longTagFixer.characters;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<!-- Delete -->
|
||||
<vbox align="center" pack="center">
|
||||
<label value="&zotero.sync.longTagFixer.tagWillBeDeleted;"/>
|
||||
</vbox>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</dialog>
|
260
chrome/content/zotero/lookup.js
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009-2011 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles UI for lookup panel
|
||||
* @namespace
|
||||
*/
|
||||
var Zotero_Lookup = new function () {
|
||||
/**
|
||||
* Performs a lookup by DOI, PMID, or ISBN
|
||||
*/
|
||||
this.accept = function(textBox) {
|
||||
var foundIDs = []; //keep track of identifiers to avoid duplicates
|
||||
var identifier = textBox.value;
|
||||
//first look for DOIs
|
||||
var ids = identifier.split(/[\s\u00A0]+/); //whitespace + non-breaking space
|
||||
var items = [], doi;
|
||||
for(var i=0, n=ids.length; i<n; i++) {
|
||||
if((doi = Zotero.Utilities.cleanDOI(ids[i])) && foundIDs.indexOf(doi) == -1) {
|
||||
items.push({itemType:"journalArticle", DOI:doi});
|
||||
foundIDs.push(doi);
|
||||
}
|
||||
}
|
||||
|
||||
//then try ISBNs
|
||||
if(!items.length) {
|
||||
//first try replacing dashes
|
||||
ids = identifier.replace(/[\u002D\u00AD\u2010-\u2015\u2212]+/g, "") //hyphens and dashes
|
||||
.toUpperCase();
|
||||
|
||||
var ISBN_RE = /(?:\D|^)(97[89]\d{10}|\d{9}[\dX])(?!\d)/g;
|
||||
var isbn;
|
||||
|
||||
while(isbn = ISBN_RE.exec(ids)) {
|
||||
isbn = Zotero.Utilities.cleanISBN(isbn[1]);
|
||||
if(isbn && foundIDs.indexOf(isbn) == -1) {
|
||||
items.push({itemType:"book", ISBN:isbn});
|
||||
foundIDs.push(isbn);
|
||||
}
|
||||
}
|
||||
|
||||
//now try spaces
|
||||
if(!items.length) {
|
||||
ids = ids.replace(/[ \u00A0]+/g, ""); //space + non-breaking space
|
||||
while(isbn = ISBN_RE.exec(ids)) {
|
||||
isbn = Zotero.Utilities.cleanISBN(isbn[1]);
|
||||
if(isbn && foundIDs.indexOf(isbn) == -1) {
|
||||
items.push({itemType:"book", ISBN:isbn});
|
||||
foundIDs.push(isbn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//finally try for PMID
|
||||
if(!items.length) {
|
||||
// PMID; right now, the longest PMIDs are 8 digits, so it doesn't
|
||||
// seem like we will need to discriminate for a fairly long time
|
||||
var PMID_RE = /(?:\D|^)(\d{1,9})(?!\d)/g;
|
||||
var pmid;
|
||||
while((pmid = PMID_RE.exec(identifier)) && foundIDs.indexOf(pmid) == -1) {
|
||||
items.push({itemType:"journalArticle", contextObject:"rft_id=info:pmid/"+pmid[1]});
|
||||
foundIDs.push(pmid);
|
||||
}
|
||||
}
|
||||
|
||||
if(!items.length) {
|
||||
Zotero.alert(
|
||||
window,
|
||||
Zotero.getString("lookup.failure.title"),
|
||||
Zotero.getString("lookup.failureToID.description")
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
var libraryID = null;
|
||||
var collection = false;
|
||||
try {
|
||||
libraryID = ZoteroPane_Local.getSelectedLibraryID();
|
||||
collection = ZoteroPane_Local.getSelectedCollection();
|
||||
} catch(e) {
|
||||
/** TODO: handle this **/
|
||||
}
|
||||
|
||||
var notDone = items.length; //counter for asynchronous fetching
|
||||
var successful = 0; //counter for successful retrievals
|
||||
|
||||
Zotero_Lookup.toggleProgress(true);
|
||||
|
||||
var item;
|
||||
while(item = items.pop()) {
|
||||
(function(item) {
|
||||
var translate = new Zotero.Translate.Search();
|
||||
translate.setSearch(item);
|
||||
|
||||
// be lenient about translators
|
||||
var translators = translate.getTranslators();
|
||||
translate.setTranslator(translators);
|
||||
|
||||
translate.setHandler("done", function(translate, success) {
|
||||
notDone--;
|
||||
successful += success;
|
||||
|
||||
if(!notDone) { //i.e. done
|
||||
Zotero_Lookup.toggleProgress(false);
|
||||
if(successful) {
|
||||
document.getElementById("zotero-lookup-panel").hidePopup();
|
||||
} else {
|
||||
Zotero.alert(
|
||||
window,
|
||||
Zotero.getString("lookup.failure.title"),
|
||||
Zotero.getString("lookup.failure.description")
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
translate.setHandler("itemDone", function(obj, item) {
|
||||
if(collection) collection.addItem(item.id);
|
||||
});
|
||||
|
||||
translate.translate(libraryID);
|
||||
})(item);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a key press
|
||||
*/
|
||||
this.onKeyPress = function(event, textBox) {
|
||||
var keyCode = event.keyCode;
|
||||
//use enter to start search, shift+enter to insert a new line. Flipped in multiline mode
|
||||
var multiline = textBox.getAttribute('multiline');
|
||||
var search = multiline ? event.shiftKey : !event.shiftKey;
|
||||
if(keyCode === 13 || keyCode === 14) {
|
||||
if(search) {
|
||||
Zotero_Lookup.accept(textBox);
|
||||
event.stopImmediatePropagation();
|
||||
} else if(!multiline) { //switch to multiline
|
||||
var mlTextbox = Zotero_Lookup.toggleMultiline(true);
|
||||
mlTextbox.value = mlTextbox.value + '\n';
|
||||
}
|
||||
} else if(keyCode == event.DOM_VK_ESCAPE) {
|
||||
document.getElementById("zotero-lookup-panel").hidePopup();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the field
|
||||
*/
|
||||
this.onShowing = function() {
|
||||
document.getElementById("zotero-lookup-panel").style.padding = "10px";
|
||||
|
||||
// Workaround for field being truncated in middle
|
||||
// https://github.com/zotero/zotero/issues/343
|
||||
this.toggleMultiline(true);
|
||||
|
||||
var identifierElement = Zotero_Lookup.toggleMultiline(false);
|
||||
Zotero_Lookup.toggleProgress(false);
|
||||
identifierElement.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the popup and resets fields
|
||||
*/
|
||||
this.onHidden = function() {
|
||||
var txtBox = Zotero_Lookup.toggleMultiline(false);
|
||||
var mlTextbox = document.getElementById("zotero-lookup-multiline-textbox");
|
||||
txtBox.value = "";
|
||||
mlTextbox.value = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the textbox to multiline if newlines are detected
|
||||
*/
|
||||
this.adjustTextbox = function(txtBox) {
|
||||
if(txtBox.value.trim().match(/[\r\n]/)) {
|
||||
Zotero_Lookup.toggleMultiline(true);
|
||||
} else {
|
||||
//since we ignore trailing and leading newlines, we should also trim them for display
|
||||
//can't use trim, because then we cannot add leading/trailing spaces to the single line textbox
|
||||
txtBox.value = txtBox.value.replace(/^([ \t]*[\r\n]+[ \t]*)+|([ \t]*[\r\n]+[ \t]*)+$/g,"");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the switch to multiline textbox and returns that textbox
|
||||
*/
|
||||
this.toggleMultiline = function(on) {
|
||||
var mlPanel = document.getElementById("zotero-lookup-multiline");
|
||||
var mlTxtBox = document.getElementById("zotero-lookup-multiline-textbox");
|
||||
var slPanel = document.getElementById("zotero-lookup-singleLine");
|
||||
var slTxtBox = document.getElementById("zotero-lookup-textbox");
|
||||
var source = on ? slTxtBox : mlTxtBox;
|
||||
var dest = on ? mlTxtBox : slTxtBox;
|
||||
|
||||
if((mlPanel.collapsed && !on) || (!mlPanel.collapsed && on)) return dest;
|
||||
|
||||
//copy over the value
|
||||
dest.value = source.value;
|
||||
|
||||
//switch textboxes
|
||||
mlPanel.setAttribute("collapsed", !on);
|
||||
slPanel.setAttribute("collapsed", !!on);
|
||||
|
||||
// Resize arrow box to fit content
|
||||
if(Zotero.isMac) {
|
||||
var panel = document.getElementById("zotero-lookup-panel");
|
||||
var box = panel.firstChild;
|
||||
panel.sizeTo(box.scrollWidth, box.scrollHeight);
|
||||
}
|
||||
|
||||
dest.focus();
|
||||
return dest;
|
||||
}
|
||||
|
||||
this.toggleProgress = function(on) {
|
||||
//single line
|
||||
var txtBox = document.getElementById("zotero-lookup-textbox");
|
||||
txtBox.style.opacity = on ? 0.5 : 1;
|
||||
txtBox.disabled = !!on;
|
||||
document.getElementById("zotero-lookup-progress").setAttribute("collapsed", !on);
|
||||
|
||||
//multiline
|
||||
document.getElementById("zotero-lookup-multiline-textbox").disabled = !!on;
|
||||
document.getElementById("zotero-lookup-multiline-progress").setAttribute("collapsed", !on);
|
||||
}
|
||||
|
||||
this.getActivePanel = function() {
|
||||
var mlPanel = document.getElementById("zotero-lookup-multiline");
|
||||
if(mlPanel.collapsed) return document.getElementById("zotero-lookup-singleLine");
|
||||
|
||||
return mlPanel;
|
||||
}
|
||||
}
|
350
chrome/content/zotero/merge.js
Normal file
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_Merge_Window = new function () {
|
||||
this.init = init;
|
||||
this.onBack = onBack;
|
||||
this.onNext = onNext;
|
||||
this.onFinish = onFinish;
|
||||
this.onCancel = onCancel;
|
||||
|
||||
var _wizard = null;
|
||||
var _wizardPage = null;
|
||||
var _mergeGroup = null;
|
||||
var _numObjects = null;
|
||||
|
||||
var _initialized = false;
|
||||
var _io = null;
|
||||
var _objects = null;
|
||||
var _merged = [];
|
||||
var _pos = -1;
|
||||
|
||||
function init() {
|
||||
_wizard = document.getElementsByTagName('wizard')[0];
|
||||
_wizardPage = document.getElementsByTagName('wizardpage')[0];
|
||||
_mergeGroup = document.getElementsByTagName('zoteromergegroup')[0];
|
||||
|
||||
_wizard.setAttribute('width', Math.min(980, screen.width - 20));
|
||||
_wizard.setAttribute('height', Math.min(718, screen.height - 30));
|
||||
|
||||
// Set font size from pref
|
||||
Zotero.setFontSize(_wizardPage);
|
||||
|
||||
_wizard.getButton('cancel').setAttribute('label', Zotero.getString('sync.cancel'));
|
||||
|
||||
_io = window.arguments[0];
|
||||
_objects = _io.dataIn.objects;
|
||||
if (!_objects.length) {
|
||||
// TODO: handle no objects
|
||||
return;
|
||||
}
|
||||
|
||||
_mergeGroup.type = _io.dataIn.type;
|
||||
_mergeGroup.onSelectionChange = _updateResolveAllCheckbox;
|
||||
|
||||
switch (_mergeGroup.type) {
|
||||
case 'item':
|
||||
case 'storagefile':
|
||||
break;
|
||||
|
||||
default:
|
||||
_error("Unsupported merge object type '" + _mergeGroup.type
|
||||
+ "' in Zotero_Merge_Window.init()");
|
||||
return;
|
||||
}
|
||||
|
||||
_mergeGroup.leftCaption = _io.dataIn.captions[0];
|
||||
_mergeGroup.rightCaption = _io.dataIn.captions[1];
|
||||
_mergeGroup.mergeCaption = _io.dataIn.captions[2];
|
||||
|
||||
_resolveAllCheckbox = document.getElementById('resolve-all');
|
||||
|
||||
_numObjects = document.getElementById('zotero-merge-num-objects');
|
||||
document.getElementById('zotero-merge-total-objects').value = _objects.length;
|
||||
|
||||
this.onNext();
|
||||
}
|
||||
|
||||
|
||||
function onBack() {
|
||||
_pos--;
|
||||
|
||||
if (_pos == 0) {
|
||||
_wizard.canRewind = false;
|
||||
}
|
||||
|
||||
_merged[_pos + 1] = _getCurrentMergeObject();
|
||||
|
||||
_numObjects.value = _pos + 1;
|
||||
|
||||
_mergeGroup.left = _objects[_pos][0];
|
||||
_mergeGroup.right = _objects[_pos][1];
|
||||
|
||||
// Restore previously merged object into merge pane
|
||||
_mergeGroup.merge = _merged[_pos].ref;
|
||||
if (_merged[_pos].id == _mergeGroup.left.id) {
|
||||
_mergeGroup.leftpane.setAttribute("selected", "true");
|
||||
_mergeGroup.rightpane.removeAttribute("selected");
|
||||
}
|
||||
else {
|
||||
_mergeGroup.leftpane.removeAttribute("selected");
|
||||
_mergeGroup.rightpane.setAttribute("selected", "true");
|
||||
}
|
||||
_updateResolveAllCheckbox();
|
||||
|
||||
if (_mergeGroup.type == 'item') {
|
||||
_updateChangedCreators();
|
||||
}
|
||||
|
||||
var nextButton = _wizard.getButton("next");
|
||||
|
||||
if (Zotero.isMac) {
|
||||
nextButton.setAttribute("hidden", "false");
|
||||
_wizard.getButton("finish").setAttribute("hidden", "true");
|
||||
}
|
||||
else {
|
||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
||||
deck.selectedIndex = 1;
|
||||
}
|
||||
|
||||
_setInstructionsString(nextButton.label);
|
||||
}
|
||||
|
||||
|
||||
function onNext() {
|
||||
if (_pos + 1 == _objects.length || _resolveAllCheckbox.checked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_pos++;
|
||||
|
||||
if (_pos == 0) {
|
||||
_wizard.canRewind = false;
|
||||
}
|
||||
else {
|
||||
_wizard.canRewind = true;
|
||||
|
||||
// Save merged object to return array
|
||||
_merged[_pos - 1] = _getCurrentMergeObject();
|
||||
}
|
||||
|
||||
// Adjust counter
|
||||
_numObjects.value = _pos + 1;
|
||||
|
||||
try {
|
||||
_mergeGroup.left = _objects[_pos][0];
|
||||
_mergeGroup.right = _objects[_pos][1];
|
||||
|
||||
// Restore previously merged object into merge pane
|
||||
if (_merged[_pos]) {
|
||||
_mergeGroup.merge = _merged[_pos].ref;
|
||||
_mergeGroup.leftpane.removeAttribute("selected");
|
||||
_mergeGroup.rightpane.removeAttribute("selected");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
_error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
_updateResolveAllCheckbox();
|
||||
|
||||
if (_mergeGroup.type == 'item') {
|
||||
_updateChangedCreators();
|
||||
}
|
||||
|
||||
if (_isLastConflict()) {
|
||||
_showFinishButton();
|
||||
}
|
||||
else {
|
||||
_showNextButton();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function onFinish() {
|
||||
// If using one side for all remaining, update merge object
|
||||
if (!_isLastConflict() && _resolveAllCheckbox.checked) {
|
||||
let useRemote = _mergeGroup.rightpane.getAttribute("selected") == "true";
|
||||
for (let i = _pos; i < _objects.length; i++) {
|
||||
_merged[i] = _getMergeObject(
|
||||
_objects[i][useRemote ? 1 : 0],
|
||||
_objects[i][0],
|
||||
_objects[i][1]
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_merged[_pos] = _getCurrentMergeObject();
|
||||
}
|
||||
|
||||
_io.dataOut = _merged;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function onCancel() {
|
||||
// if already merged, ask
|
||||
}
|
||||
|
||||
|
||||
this.onResolveAllChange = function (resolveAll) {
|
||||
if (resolveAll || _isLastConflict()) {
|
||||
_showFinishButton();
|
||||
}
|
||||
else {
|
||||
_showNextButton();
|
||||
}
|
||||
}
|
||||
|
||||
function _updateResolveAllCheckbox() {
|
||||
if (_mergeGroup.rightpane.getAttribute("selected") == 'true') {
|
||||
var label = 'sync.merge.resolveAllRemote';
|
||||
}
|
||||
else {
|
||||
var label = 'sync.merge.resolveAllLocal';
|
||||
}
|
||||
_resolveAllCheckbox.label = Zotero.getString(label);
|
||||
}
|
||||
|
||||
|
||||
function _isLastConflict() {
|
||||
return (_pos + 1) == _objects.length;
|
||||
}
|
||||
|
||||
|
||||
function _showNextButton() {
|
||||
var nextButton = _wizard.getButton("next");
|
||||
|
||||
if (Zotero.isMac) {
|
||||
nextButton.setAttribute("hidden", "false");
|
||||
_wizard.getButton("finish").setAttribute("hidden", "true");
|
||||
}
|
||||
else {
|
||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
||||
deck.selectedIndex = 1;
|
||||
}
|
||||
|
||||
_setInstructionsString(nextButton.label);
|
||||
}
|
||||
|
||||
|
||||
function _showFinishButton() {
|
||||
var finishButton = _wizard.getButton("finish");
|
||||
|
||||
if (Zotero.isMac) {
|
||||
_wizard.getButton("next").setAttribute("hidden", "true");
|
||||
finishButton.setAttribute("hidden", "false");
|
||||
}
|
||||
// Windows uses a deck to switch between the Next and Finish buttons
|
||||
// TODO: check Linux
|
||||
else {
|
||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
||||
deck.selectedIndex = 0;
|
||||
}
|
||||
|
||||
_setInstructionsString(finishButton.label);
|
||||
}
|
||||
|
||||
|
||||
function _getMergeObject(ref, left, right) {
|
||||
var id = ref == 'deleted'
|
||||
? (left == 'deleted' ? right.id : left.id)
|
||||
: ref.id;
|
||||
|
||||
return {
|
||||
id: id,
|
||||
ref: ref,
|
||||
left: left,
|
||||
right: right
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function _getCurrentMergeObject() {
|
||||
return _getMergeObject(_mergeGroup.merge, _mergeGroup.left, _mergeGroup.right);
|
||||
}
|
||||
|
||||
|
||||
// Hack to support creator reconciliation via item view
|
||||
function _updateChangedCreators() {
|
||||
if (_mergeGroup.type != 'item') {
|
||||
_error("_updateChangedCreators called on non-item object in "
|
||||
+ "Zotero_Merge_Window._updateChangedCreators()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_io.dataIn.changedCreators) {
|
||||
var originalCreators = _mergeGroup.rightpane.original.getCreators();
|
||||
var clonedCreators = _mergeGroup.rightpane.ref.getCreators();
|
||||
var refresh = false;
|
||||
for (var i in originalCreators) {
|
||||
var changedCreator = _io.dataIn.changedCreators[Zotero.Creators.getLibraryKeyHash(originalCreators[i].ref)];
|
||||
if (changedCreator) {
|
||||
_mergeGroup.rightpane.original.setCreator(
|
||||
i, changedCreator, originalCreators[i].creatorTypeID
|
||||
);
|
||||
clonedCreators[i].ref = changedCreator;
|
||||
refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
_mergeGroup.rightpane.objectbox.refresh();
|
||||
_mergeGroup.mergepane.objectbox.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TEMP
|
||||
function _setInstructionsString(buttonName) {
|
||||
switch (_mergeGroup.type) {
|
||||
case 'storagefile':
|
||||
var msg = Zotero.getString('sync.conflict.fileChanged');
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: cf. localization: maybe not always call it 'item'
|
||||
var msg = Zotero.getString('sync.conflict.itemChanged');
|
||||
}
|
||||
|
||||
msg += " " + Zotero.getString('sync.conflict.chooseVersionToKeep', buttonName);
|
||||
|
||||
document.getElementById('zotero-merge-instructions').value = msg;
|
||||
}
|
||||
|
||||
|
||||
function _error(e) {
|
||||
Zotero.debug(e);
|
||||
_io.error = e;
|
||||
_wizard.getButton('cancel').click();
|
||||
}
|
||||
}
|
65
chrome/content/zotero/merge.xul
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/merge.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<wizard
|
||||
id="zotero-merge-window"
|
||||
orient="vertical"
|
||||
title=""
|
||||
onwizardfinish="return Zotero_Merge_Window.onFinish()"
|
||||
onwizardcancel="return Zotero_Merge_Window.onCancel()"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="merge.js"/>
|
||||
|
||||
<wizardpage onpageshow="Zotero_Merge_Window.init()"
|
||||
onpagerewound="Zotero_Merge_Window.onBack(); return false"
|
||||
onpageadvanced="return Zotero_Merge_Window.onNext()"
|
||||
label="&zotero.merge.title;">
|
||||
<description id="zotero-merge-instructions"/>
|
||||
<zoteromergegroup flex="1"/>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<separator orient="vertical" flex="1"/>
|
||||
<hbox>
|
||||
<checkbox id="resolve-all"
|
||||
oncommand="Zotero_Merge_Window.onResolveAllChange(this.checked)"/>
|
||||
</hbox>
|
||||
<separator orient="vertical"/>
|
||||
<hbox id="zotero-step-count">
|
||||
<label id="zotero-merge-num-objects"/>
|
||||
<label value="&zotero.merge.of;"/>
|
||||
<label id="zotero-merge-total-objects"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</wizardpage>
|
||||
</wizard>
|
104
chrome/content/zotero/note.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var noteEditor;
|
||||
var notifierUnregisterID;
|
||||
|
||||
function onLoad() {
|
||||
noteEditor = document.getElementById('zotero-note-editor');
|
||||
noteEditor.mode = 'edit';
|
||||
noteEditor.focus();
|
||||
|
||||
// Set font size from pref
|
||||
Zotero.setFontSize(noteEditor);
|
||||
|
||||
if (window.arguments) {
|
||||
var io = window.arguments[0];
|
||||
}
|
||||
var itemID = io.itemID;
|
||||
var collectionID = io.collectionID;
|
||||
var parentItemID = io.parentItemID;
|
||||
|
||||
if (itemID) {
|
||||
var ref = Zotero.Items.get(itemID);
|
||||
|
||||
var clearUndo = noteEditor.item ? noteEditor.item.id != ref.id : false;
|
||||
|
||||
noteEditor.item = ref;
|
||||
|
||||
// If loading new or different note, disable undo while we repopulate the text field
|
||||
// so Undo doesn't end up clearing the field. This also ensures that Undo doesn't
|
||||
// undo content from another note into the current one.
|
||||
if (clearUndo) {
|
||||
noteEditor.clearUndo();
|
||||
}
|
||||
|
||||
document.title = ref.getNoteTitle();
|
||||
}
|
||||
else {
|
||||
if (parentItemID) {
|
||||
var ref = Zotero.Items.get(parentItemID);
|
||||
noteEditor.parent = ref;
|
||||
}
|
||||
else {
|
||||
if (collectionID && collectionID != '' && collectionID != 'undefined') {
|
||||
noteEditor.collection = Zotero.Collections.get(collectionID);
|
||||
}
|
||||
}
|
||||
noteEditor.refresh();
|
||||
}
|
||||
|
||||
notifierUnregisterID = Zotero.Notifier.registerObserver(NotifyCallback, 'item');
|
||||
}
|
||||
|
||||
function onUnload()
|
||||
{
|
||||
if(noteEditor && noteEditor.value)
|
||||
noteEditor.save();
|
||||
|
||||
Zotero.Notifier.unregisterObserver(notifierUnregisterID);
|
||||
}
|
||||
|
||||
var NotifyCallback = {
|
||||
notify: function(action, type, ids){
|
||||
if (noteEditor.item && ids.indexOf(noteEditor.item.id) != -1) {
|
||||
noteEditor.item = noteEditor.item;
|
||||
|
||||
// If the document title hasn't yet been set, reset undo so
|
||||
// undoing to empty isn't possible
|
||||
var noteTitle = noteEditor.note.getNoteTitle();
|
||||
if (!document.title && noteTitle != '') {
|
||||
noteEditor.clearUndo();
|
||||
document.title = noteTitle;
|
||||
}
|
||||
|
||||
// Update the window name (used for focusing) in case this is a new note
|
||||
window.name = 'zotero-note-' + noteEditor.item.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("load", function(e) { onLoad(e); }, false);
|
||||
addEventListener("unload", function(e) { onUnload(e); }, false);
|
27
chrome/content/zotero/note.xul
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<window
|
||||
id="zotero-note-window"
|
||||
orient="vertical"
|
||||
width="400"
|
||||
height="350"
|
||||
title="&zotero.items.menu.attach.note;"
|
||||
persist="screenX screenY width height"
|
||||
windowtype="zotero:note"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script src="include.js"/>
|
||||
<script src="itemPane.js"/>
|
||||
<script src="note.js"/>
|
||||
|
||||
<keyset>
|
||||
<key id="key_close" key="W" modifiers="accel" command="cmd_close"/>
|
||||
</keyset>
|
||||
<command id="cmd_close" oncommand="window.close();"/>
|
||||
|
||||
<zoteronoteeditor id="zotero-note-editor" flex="1"/>
|
||||
</window>
|
294
chrome/content/zotero/overlay.js
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/*
|
||||
* This object contains the various functions for the interface
|
||||
*/
|
||||
var ZoteroOverlay = new function()
|
||||
{
|
||||
const DEFAULT_ZPANE_HEIGHT = 300;
|
||||
var toolbarCollapseState, showInPref;
|
||||
var zoteroPane, zoteroSplitter;
|
||||
var _stateBeforeReload = false;
|
||||
|
||||
this.isTab = false;
|
||||
|
||||
this.onLoad = function() {
|
||||
try {
|
||||
|
||||
zoteroPane = document.getElementById('zotero-pane-stack');
|
||||
zoteroSplitter = document.getElementById('zotero-splitter');
|
||||
|
||||
ZoteroPane_Overlay = ZoteroPane;
|
||||
ZoteroPane.init();
|
||||
|
||||
// Open Zotero app tab, if in Fx 4 and requested by pref
|
||||
showInPref = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService)
|
||||
.getBranch('extensions.zotero.').getIntPref('showIn');
|
||||
this.isTab = showInPref !== 1;
|
||||
|
||||
var observerService = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
var zoteroObserver = function(subject, topic, data) {
|
||||
if(subject != window) return;
|
||||
observerService.removeObserver(this, "browser-delayed-startup-finished");
|
||||
if(showInPref === 3) {
|
||||
var tabbar = document.getElementById("TabsToolbar");
|
||||
if(tabbar && window.getComputedStyle(tabbar).display !== "none") {
|
||||
// load Zotero as a tab, if it isn't loading by default
|
||||
ZoteroOverlay.loadZoteroTab(true);
|
||||
}
|
||||
} else if(showInPref === 1) {
|
||||
// close Zotero as a tab, in case it was pinned
|
||||
var zoteroTab = ZoteroOverlay.findZoteroTab();
|
||||
if(zoteroTab) gBrowser.removeTab(zoteroTab);
|
||||
}
|
||||
};
|
||||
|
||||
observerService.addObserver(zoteroObserver, "browser-delayed-startup-finished", false);
|
||||
|
||||
// Set a flag for hi-res displays
|
||||
Zotero.hiDPI = window.devicePixelRatio > 1;
|
||||
|
||||
// Clear old Zotero icon pref
|
||||
var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService)
|
||||
.getBranch('extensions.zotero.');
|
||||
prefBranch.clearUserPref('statusBarIcon');
|
||||
|
||||
// Add toolbar icon
|
||||
Services.scriptloader.loadSubScript("chrome://zotero/content/icon.js", {}, "UTF-8");
|
||||
|
||||
if (Zotero && Zotero.initialized){
|
||||
// TODO: Add only when progress window is open
|
||||
document.getElementById('appcontent').addEventListener('mousemove', Zotero.ProgressWindowSet.updateTimers, false);
|
||||
}
|
||||
|
||||
// Used for loading pages from upgrade wizard
|
||||
if (Zotero && Zotero.initialURL) {
|
||||
setTimeout(function () {
|
||||
gBrowser.selectedTab = gBrowser.addTab(Zotero.initialURL);
|
||||
Zotero.initialURL = null;
|
||||
}, 1);
|
||||
}
|
||||
|
||||
// Hide browser chrome on Zotero tab
|
||||
XULBrowserWindow.inContentWhitelist.push("chrome://zotero/content/tab.xul");
|
||||
|
||||
// Close pane before reload
|
||||
ZoteroPane_Local.addBeforeReloadListener(function(newMode) {
|
||||
if(newMode == "connector") {
|
||||
// save current state
|
||||
_stateBeforeReload = !zoteroPane.hidden && !zoteroPane.collapsed;
|
||||
|
||||
// Don't display startup error when Standalone opens
|
||||
if (Zotero.startupError) {
|
||||
Zotero.debug(startupError, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure pane is closed
|
||||
if(!zoteroPane.collapsed) ZoteroOverlay.toggleDisplay(false, true);
|
||||
}
|
||||
});
|
||||
|
||||
// Close pane if connector is enabled
|
||||
ZoteroPane_Local.addReloadListener(function() {
|
||||
if(!Zotero.isConnector) {
|
||||
// reopen pane if it was open before
|
||||
ZoteroOverlay.toggleDisplay(_stateBeforeReload, true);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.onUnload = function() {
|
||||
ZoteroPane.destroy();
|
||||
}
|
||||
|
||||
this.onBeforeUnload = function() {
|
||||
// close Zotero as a tab, so it won't be pinned
|
||||
var zoteroTab = ZoteroOverlay.findZoteroTab();
|
||||
if(zoteroTab) gBrowser.removeTab(zoteroTab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides/displays the Zotero interface
|
||||
* @param {Boolean} makeVisible Whether or not Zotero interface should be visible
|
||||
* @param {Boolean} dontRefocus If true, don't focus content when closing Zotero pane. Used
|
||||
* when closing pane because Zotero Standalone is being opened, to avoid pulling Firefox to
|
||||
* the foreground.
|
||||
*/
|
||||
this.toggleDisplay = function(makeVisible, dontRefocus)
|
||||
{
|
||||
if(!Zotero || !Zotero.initialized) {
|
||||
ZoteroPane.displayStartupError();
|
||||
return;
|
||||
}
|
||||
|
||||
if(makeVisible || makeVisible === undefined) {
|
||||
if(Zotero.isConnector) {
|
||||
// If in connector mode, bring Zotero Standalone to foreground
|
||||
Zotero.activateStandalone();
|
||||
return;
|
||||
} else if(this.isTab) {
|
||||
// If in separate tab mode, just open the tab
|
||||
this.loadZoteroTab();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(makeVisible === undefined) makeVisible = zoteroPane.hidden || zoteroPane.collapsed;
|
||||
|
||||
/*
|
||||
Zotero.debug("zoteroPane.boxObject.height: " + zoteroPane.boxObject.height);
|
||||
Zotero.debug("zoteroPane.getAttribute('height'): " + zoteroPane.getAttribute('height'));
|
||||
Zotero.debug("zoteroPane.getAttribute('minheight'): " + zoteroPane.getAttribute('minheight'));
|
||||
Zotero.debug("savedHeight: " + savedHeight);
|
||||
*/
|
||||
|
||||
if(makeVisible) {
|
||||
if (Zotero.locked) {
|
||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
var msg = Zotero.getString('general.operationInProgress') + '\n\n' + Zotero.getString('general.operationInProgress.waitUntilFinished');
|
||||
ps.alert(null, "", msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
zoteroSplitter.setAttribute('hidden', false);
|
||||
zoteroPane.setAttribute('hidden', false);
|
||||
zoteroPane.setAttribute('collapsed', false);
|
||||
|
||||
// Get saved height (makeVisible() may change it)
|
||||
if (zoteroPane.hasAttribute('savedHeight')) {
|
||||
var savedHeight = zoteroPane.getAttribute('savedHeight');
|
||||
}
|
||||
else {
|
||||
var savedHeight = DEFAULT_ZPANE_HEIGHT;
|
||||
}
|
||||
|
||||
// Restore height
|
||||
var max = document.getElementById('appcontent').boxObject.height
|
||||
- zoteroSplitter.boxObject.height;
|
||||
zoteroPane.setAttribute('height', Math.min(savedHeight, max));
|
||||
|
||||
// Make visible
|
||||
ZoteroPane.makeVisible();
|
||||
|
||||
// Make sure tags splitter isn't missing for people upgrading from <2.0b7
|
||||
document.getElementById('zotero-tags-splitter').collapsed = false;
|
||||
} else {
|
||||
ZoteroPane.makeHidden();
|
||||
|
||||
// Collapse pane
|
||||
zoteroSplitter.setAttribute('hidden', true);
|
||||
zoteroPane.setAttribute('collapsed', true);
|
||||
zoteroPane.height = 0;
|
||||
|
||||
document.getElementById('content').setAttribute('collapsed', false);
|
||||
|
||||
if(!dontRefocus) {
|
||||
// Return focus to the browser content pane
|
||||
window.content.window.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether there is an open Zotero tab
|
||||
*/
|
||||
this.findZoteroTab = function() {
|
||||
// Look for an existing tab
|
||||
var tab = false;
|
||||
var numTabs = gBrowser.browsers.length;
|
||||
for(var index = 0; index < numTabs; index++) {
|
||||
var currentBrowser = gBrowser.getBrowserAtIndex(index);
|
||||
if(ZOTERO_TAB_URL == currentBrowser.currentURI.spec) {
|
||||
tab = (gBrowser.tabs ? gBrowser.tabs : gBrowser.mTabs)[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the Zotero tab, or adds a new tab if no tab yet exists
|
||||
* @param {Boolean} background Whether the Zotero tab should be loaded in the background
|
||||
*/
|
||||
this.loadZoteroTab = function(background) {
|
||||
var tab = this.findZoteroTab();
|
||||
|
||||
// If no existing tab, add a new tab
|
||||
if(!tab) tab = gBrowser.addTab(ZOTERO_TAB_URL);
|
||||
// Pin tab
|
||||
if(showInPref == 3) gBrowser.pinTab(tab);
|
||||
// If requested, activate tab
|
||||
if(!background) gBrowser.selectedTab = tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle between Zotero as a tab and Zotero as a pane
|
||||
*/
|
||||
this.toggleTab = function(setMode) {
|
||||
var tab = this.findZoteroTab();
|
||||
window.zoteroSavedItemSelection = ZoteroPane.itemsView.saveSelection();
|
||||
window.zoteroSavedCollectionSelection = ZoteroPane.collectionsView.saveSelection();
|
||||
if(tab) { // Zotero is running in a tab
|
||||
if(setMode) return;
|
||||
// if Zotero tab is the only tab, open the home page in a new tab
|
||||
if((gBrowser.tabs ? gBrowser.tabs : gBrowser.mTabs).length === 1) {
|
||||
gBrowser.addTab(gBrowser.homePage);
|
||||
}
|
||||
|
||||
// swap ZoteroPane object
|
||||
ZoteroPane = ZoteroPane_Overlay;
|
||||
|
||||
// otherwise, close Zotero tab and open Zotero pane
|
||||
gBrowser.removeTab(tab);
|
||||
this.isTab = false;
|
||||
this.toggleDisplay();
|
||||
} else { // Zotero is running in the pane
|
||||
if(setMode === false) return;
|
||||
// close Zotero pane
|
||||
this.toggleDisplay(false);
|
||||
|
||||
// open Zotero tab
|
||||
this.isTab = true;
|
||||
this.loadZoteroTab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", function(e) { ZoteroOverlay.onLoad(e); }, false);
|
||||
window.addEventListener("unload", function(e) { ZoteroOverlay.onUnload(e); }, false);
|
||||
window.addEventListener("beforeunload", function(e) { ZoteroOverlay.onBeforeUnload(e); }, false);
|
92
chrome/content/zotero/overlay.xul
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
-->
|
||||
|
||||
|
||||
<?xul-overlay href="chrome://zotero/content/zoteroPane.xul"?>
|
||||
<?xul-overlay href="chrome://zotero/content/itemPane.xul"?>
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
|
||||
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd"> %zoteroDTD;
|
||||
]>
|
||||
|
||||
<overlay id="zotero"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<!-- Include the global XPCOM object -->
|
||||
<script src="overlay.js"/>
|
||||
|
||||
<popup id="contentAreaContextMenu"/>
|
||||
|
||||
<toolbar id="zotero-toolbar" nowindowdrag="true"/>
|
||||
|
||||
<vbox id="appcontent">
|
||||
<!-- onmouseup shouldn't be necessary but seems to help prevent tag selector from sometimes going off the screen -->
|
||||
<splitter id="zotero-splitter" resizebefore="closest" resizeafter="closest" hidden="true"
|
||||
onmouseup="ZoteroPane.updateTagSelectorSize()"/>
|
||||
|
||||
<stack id="zotero-pane-stack" persist="savedHeight" savedHeight="300" hidden="true"/>
|
||||
|
||||
<zoteroguidancepanel id="zotero-main-button-guidance" about="toolbarButton" for="zotero-toolbar-main-button"
|
||||
position="bottomcenter topleft" delay="2000" foregroundonly="true" noautohide="true"
|
||||
hideonpagechange="true" forward="zotero-save-button-guidance"/>
|
||||
<zoteroguidancepanel id="zotero-save-button-guidance" about="saveButton" for="zotero-toolbar-save-button"
|
||||
position="bottomcenter topleft" x="-8" delay="2000" foregroundonly="true" noautohide="true"
|
||||
hideonpagechange="true"/>
|
||||
|
||||
<!-- Annotation Toolbar -->
|
||||
<toolbar id="zotero-annotate-tb" crop="end" insertbefore="content" hidden="true">
|
||||
<toolbarbutton id="zotero-annotate-tb-add" tooltiptext="&zotero.annotate.toolbar.add.label;" oncommand="Zotero_Browser.toggleMode(this.id);"/>
|
||||
<toolbarbutton id="zotero-annotate-tb-collapse" tooltiptext="&zotero.annotate.toolbar.collapse.label;" oncommand="Zotero_Browser.toggleCollapsed();"/>
|
||||
<toolbarseparator/>
|
||||
<toolbarbutton id="zotero-annotate-tb-highlight" tooltiptext="&zotero.annotate.toolbar.highlight.label;" oncommand="Zotero_Browser.toggleMode(this.id);"/>
|
||||
<toolbarbutton id="zotero-annotate-tb-unhighlight" tooltiptext="&zotero.annotate.toolbar.unhighlight.label;" oncommand="Zotero_Browser.toggleMode(this.id);"/>
|
||||
</toolbar>
|
||||
</vbox>
|
||||
|
||||
|
||||
<menupopup id="menu_ToolsPopup">
|
||||
<menuseparator id="zoteroSeparator" insertbefore="devToolsSeparator"/>
|
||||
<menuitem id="tools-zotero" insertbefore="devToolsSeparator"
|
||||
oncommand="ZoteroOverlay.toggleDisplay();" label="Zotero"
|
||||
key="key_openZotero"/>
|
||||
</menupopup>
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<!--
|
||||
The key can be changed by the pref extensions.zotero.keys.openZotero,
|
||||
but if the values are changed here, the pref won't override them.
|
||||
-->
|
||||
<key id="key_openZotero"
|
||||
key="Z"
|
||||
oncommand="ZoteroOverlay.toggleDisplay();"
|
||||
modifiers="accel shift" />
|
||||
<key id="key_saveToZotero"
|
||||
key="S"
|
||||
oncommand="Zotero_Browser.scrapeThisPage();"
|
||||
modifiers="accel shift" />
|
||||
</keyset>
|
||||
</overlay>
|
25
chrome/content/zotero/pdfProgress.xul
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" ?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&zotero.progress.title;" width="550" height="230"
|
||||
id="zotero-progress">
|
||||
<vbox style="padding:10px" flex="1">
|
||||
<label id="label" control="progress-indicator" value="&zotero.recognizePDF.recognizing.label;"/>
|
||||
<hbox align="center">
|
||||
<progressmeter id="progress-indicator" mode="determined" flex="1"/>
|
||||
<button id="cancel-button" label="&zotero.recognizePDF.cancel.label;"/>
|
||||
</hbox>
|
||||
<tree flex="1" id="tree" hidecolumnpicker="true">
|
||||
<treecols>
|
||||
<treecol id="success-col" style="width:20px;"/>
|
||||
<splitter class="tree-splitter" hidden="true"/>
|
||||
<treecol label="&zotero.recognizePDF.pdfName.label;" id="pdf-col" flex="1"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&zotero.recognizePDF.itemName.label;" id="item-col" flex="2"/>
|
||||
</treecols>
|
||||
<treechildren id="treechildren"/>
|
||||
</tree>
|
||||
</vbox>
|
||||
</window>
|
132
chrome/content/zotero/preferences/preferences.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2006–2013 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var Zotero_Preferences = {
|
||||
init: function () {
|
||||
if(Zotero.isConnector) {
|
||||
Zotero.activateStandalone();
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
observerService.addObserver(function() {
|
||||
if(Zotero.isConnector) window.close();
|
||||
}, "zotero-reloaded", false);
|
||||
|
||||
if(window.arguments) {
|
||||
var io = window.arguments[0];
|
||||
|
||||
if(io.pane) {
|
||||
var pane = document.getElementById(io.pane);
|
||||
document.getElementById('zotero-prefs').showPane(pane);
|
||||
}
|
||||
} else if(document.location.hash == "#cite") {
|
||||
document.getElementById('zotero-prefs').showPane(document.getElementById("zotero-prefpane-cite"));
|
||||
}
|
||||
},
|
||||
|
||||
onUnload: function () {
|
||||
if (Zotero_Preferences.Debug_Output) {
|
||||
Zotero_Preferences.Debug_Output.onUnload();
|
||||
}
|
||||
},
|
||||
|
||||
openURL: function (url, windowName) {
|
||||
// Non-instantApply prefwindows are usually modal, so we can't open in the topmost window,
|
||||
// since it's probably behind the window
|
||||
var instantApply = Zotero.Prefs.get("browser.preferences.instantApply", true);
|
||||
|
||||
if (instantApply) {
|
||||
window.opener.ZoteroPane_Local.loadURI(url, { shiftKey: true, metaKey: true });
|
||||
}
|
||||
else {
|
||||
if (Zotero.isStandalone) {
|
||||
var io = Components.classes['@mozilla.org/network/io-service;1']
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var uri = io.newURI(url, null, null);
|
||||
var handler = Components.classes['@mozilla.org/uriloader/external-protocol-service;1']
|
||||
.getService(Components.interfaces.nsIExternalProtocolService)
|
||||
.getProtocolHandlerInfo('http');
|
||||
handler.preferredAction = Components.interfaces.nsIHandlerInfo.useSystemDefault;
|
||||
handler.launchWithURI(uri, null);
|
||||
}
|
||||
else {
|
||||
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
var win = ww.openWindow(
|
||||
window,
|
||||
url,
|
||||
windowName ? windowName : null,
|
||||
"chrome=no,menubar=yes,location=yes,toolbar=yes,personalbar=yes,resizable=yes,scrollbars=yes,status=yes",
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
openHelpLink: function () {
|
||||
var url = "http://www.zotero.org/support/preferences/";
|
||||
var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
|
||||
url += helpTopic;
|
||||
|
||||
this.openURL(url, "helpWindow");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Opens a URI in the basic viewer in Standalone, or a new window in Firefox
|
||||
*/
|
||||
openInViewer: function (uri, newTab) {
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
const features = "menubar=yes,toolbar=no,location=no,scrollbars,centerscreen,resizable";
|
||||
|
||||
if(Zotero.isStandalone) {
|
||||
var win = wm.getMostRecentWindow("zotero:basicViewer");
|
||||
if(win) {
|
||||
win.loadURI(uri);
|
||||
} else {
|
||||
window.openDialog("chrome://zotero/content/standalone/basicViewer.xul",
|
||||
"basicViewer", "chrome,resizable,centerscreen,menubar,scrollbars", uri);
|
||||
}
|
||||
} else {
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
if(win) {
|
||||
if(newTab) {
|
||||
win.gBrowser.selectedTab = win.gBrowser.addTab(uri);
|
||||
} else {
|
||||
win.open(uri, null, features);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
var win = ww.openWindow(null, uri, null, features + ",width=775,height=575", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|