Compare commits
No commits in common. "ci" and "6.0" have entirely different histories.
29
.babelrc
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"compact": false,
|
||||
"retainLines": true,
|
||||
"presets": [
|
||||
"@babel/preset-react"
|
||||
],
|
||||
"ignore": [
|
||||
"chrome/content/zotero/include.js",
|
||||
"chrome/content/zotero/xpcom/citeproc.js",
|
||||
"chrome/content/ace/*",
|
||||
"chrome/content/scaffold/templates/*",
|
||||
"resource/react.js",
|
||||
"resource/react-dom.js",
|
||||
"resource/react-virtualized.js",
|
||||
"test/resource/*.js"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-object-rest-spread",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
"@babel/plugin-proposal-unicode-property-regex",
|
||||
[
|
||||
"transform-es2015-modules-commonjs",
|
||||
{
|
||||
"strictMode": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
18
.eslintignore
Normal file
|
@ -0,0 +1,18 @@
|
|||
build/*
|
||||
chrome/content/zotero/xpcom/citeproc.js
|
||||
chrome/content/zotero/xpcom/isbn.js
|
||||
chrome/content/zotero/xpcom/rdf/*
|
||||
chrome/content/zotero/xpcom/xregexp/*
|
||||
chrome/content/zotero/xpcom/translation/tlds.js
|
||||
chrome/skin/default/zotero/timeline/bundle.js
|
||||
chrome/skin/default/zotero/timeline/timeline-api.js
|
||||
resource/bluebird/*
|
||||
resource/classnames.js
|
||||
resource/csl-validator.js
|
||||
resource/jspath.js
|
||||
resource/prop-types.js
|
||||
resource/react*
|
||||
resource/schema/connectorTypeSchemaData.js
|
||||
resource/tinymce/*
|
||||
test/resource/*
|
||||
translators/*
|
44
.eslintrc
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"globals": {
|
||||
"Zotero": false,
|
||||
"ZOTERO_CONFIG": false,
|
||||
"AddonManager": false,
|
||||
"Cc": false,
|
||||
"Ci": false,
|
||||
"Components": false,
|
||||
"ConcurrentCaller": false,
|
||||
"ctypes": false,
|
||||
"OS": false,
|
||||
"PluralForm": false,
|
||||
"Services": false,
|
||||
"XPCOMUtils": false,
|
||||
"XRegExp": false
|
||||
},
|
||||
"extends": [
|
||||
"@zotero",
|
||||
"plugin:react/recommended"
|
||||
],
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"react",
|
||||
"@babel"
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "17.0"
|
||||
}
|
||||
},
|
||||
"rules": {}
|
||||
}
|
|
@ -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
|
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.sql text eol=lf
|
9
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
**READ THIS BEFORE CREATING AN ISSUE**
|
||||
|
||||
Zotero does not use GitHub Issues for bug reports or feature requests.
|
||||
|
||||
Please post all such requests to the Zotero Forums at https://forums.zotero.org, where Zotero developers and many others can help. For confirmed bugs or agreed-upon changes, Zotero developers will create new issues in the relevant repositories.
|
||||
|
||||
Development questions involving code, APIs, or other technical topics can be posted to the zotero-dev mailing list at http://groups.google.com/group/zotero-dev.
|
||||
|
||||
See https://www.zotero.org/support/zotero_support for more information on how Zotero support works.
|
93
.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
name: CI
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
name: Build, Upload, Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
#cache: npm
|
||||
|
||||
# On GitHub
|
||||
- name: Install xvfb
|
||||
if: env.ACT != 'true'
|
||||
run: sudo apt update && sudo apt install -y xvfb
|
||||
|
||||
# Local via act
|
||||
- name: Install packages for act
|
||||
if: env.ACT == 'true'
|
||||
run: apt update && apt install -y zstd xvfb dbus-x11 libgtk-3-0 libx11-xcb1 libdbus-glib-1-2 libxt6
|
||||
|
||||
- name: Cache Firefox
|
||||
id: firefox-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: firefox-x86_64
|
||||
key: firefox-60.9.0esr
|
||||
|
||||
- name: Download Firefox
|
||||
if: steps.firefox-cache.outputs.cache-hit != 'true'
|
||||
run: wget -O tarball "https://zotero-download.s3.us-east-1.amazonaws.com/dev/firefox-60.9.0esr-x86_64-modified.tar.gz"
|
||||
|
||||
- name: Extract Firefox
|
||||
if: steps.firefox-cache.outputs.cache-hit != 'true'
|
||||
run: tar xvf tarball
|
||||
|
||||
- name: Cache Node modules
|
||||
id: node-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ hashFiles('package-lock.json') }}
|
||||
|
||||
- name: Install Node modules
|
||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||
run: npm install
|
||||
|
||||
- name: Build Zotero
|
||||
run: npm run build
|
||||
# Currently necessary for pdf-worker Webpack: https://stackoverflow.com/a/69746937
|
||||
env:
|
||||
NODE_OPTIONS: --openssl-legacy-provider
|
||||
|
||||
- name: Upload deployment ZIP
|
||||
if: |
|
||||
env.ACT != 'true'
|
||||
&& github.repository == 'zotero/zotero'
|
||||
&& github.event_name == 'push'
|
||||
&& (github.ref == 'refs/heads/6.0' || endsWith(github.ref, '-hotfix') || github.ref == 'refs/heads/gh-actions-ci-test')
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
run: |
|
||||
mkdir build-zip
|
||||
cd build
|
||||
zip -r ../build-zip/$GITHUB_SHA.zip *
|
||||
cd ..
|
||||
sudo gem install --no-document dpl dpl-s3
|
||||
dpl --provider=s3 --bucket=zotero-download --local-dir=build-zip --upload-dir=ci/client --acl=public-read --skip_cleanup=true
|
||||
|
||||
- name: Run tests
|
||||
run: xvfb-run test/runtests.sh -x firefox-x86_64/firefox -f
|
||||
|
||||
- name: Cache utilities Node modules
|
||||
id: utilities-node-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: chrome/content/zotero/xpcom/utilities/node_modules
|
||||
key: utilities-node-modules-${{ hashFiles('chrome/content/zotero/xpcom/utilities/package-lock.json') }}
|
||||
|
||||
- name: Install utilities Node modules
|
||||
if: steps.utilities-node-cache.outputs.cache-hit != 'true'
|
||||
run: npm install --prefix chrome/content/zotero/xpcom/utilities
|
||||
|
||||
- name: Run utilities tests
|
||||
run: |
|
||||
npm test --prefix chrome/content/zotero/xpcom/utilities -- -j resource/schema/global/schema.json
|
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
build
|
||||
.signatures.json
|
||||
tmp
|
49
.gitmodules
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
[submodule "translators"]
|
||||
path = translators
|
||||
url = https://github.com/zotero/translators.git
|
||||
branch = master
|
||||
[submodule "chrome/content/zotero/locale/csl"]
|
||||
path = chrome/content/zotero/locale/csl
|
||||
url = https://github.com/citation-style-language/locales.git
|
||||
branch = master
|
||||
[submodule "styles"]
|
||||
path = styles
|
||||
url = https://github.com/zotero/bundled-styles.git
|
||||
branch = master
|
||||
[submodule "test/resource/chai"]
|
||||
path = test/resource/chai
|
||||
url = https://github.com/chaijs/chai.git
|
||||
branch = master
|
||||
[submodule "test/resource/mocha"]
|
||||
path = test/resource/mocha
|
||||
url = https://github.com/mochajs/mocha.git
|
||||
branch = master
|
||||
[submodule "test/resource/chai-as-promised"]
|
||||
path = test/resource/chai-as-promised
|
||||
url = https://github.com/domenic/chai-as-promised.git
|
||||
branch = master
|
||||
[submodule "resource/schema/global"]
|
||||
path = resource/schema/global
|
||||
url = https://github.com/zotero/zotero-schema.git
|
||||
branch = master
|
||||
[submodule "resource/SingleFile"]
|
||||
path = resource/SingleFile
|
||||
url = https://github.com/gildas-lormeau/SingleFile.git
|
||||
[submodule "pdf-reader"]
|
||||
path = pdf-reader
|
||||
url = https://github.com/zotero/pdf-reader.git
|
||||
branch = master
|
||||
[submodule "pdf-worker"]
|
||||
path = pdf-worker
|
||||
url = https://github.com/zotero/pdf-worker.git
|
||||
branch = master
|
||||
[submodule "note-editor"]
|
||||
path = note-editor
|
||||
url = https://github.com/zotero/note-editor.git
|
||||
branch = master
|
||||
[submodule "chrome/content/zotero/xpcom/utilities"]
|
||||
path = chrome/content/zotero/xpcom/utilities
|
||||
url = https://github.com/zotero/utilities.git
|
||||
[submodule "chrome/content/zotero/xpcom/translate"]
|
||||
path = chrome/content/zotero/xpcom/translate
|
||||
url = https://github.com/zotero/translate.git
|
11
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Contributing to Zotero
|
||||
|
||||
## Bug Reports and Feature Requests
|
||||
|
||||
Zotero does not use GitHub Issues for bug reports, feature requests, or support questions. Please post all such requests to the [Zotero Forums](https://forums.zotero.org), where Zotero developers and many others can help. See [How Zotero Support Works](https://www.zotero.org/support/zotero_support) for more information.
|
||||
|
||||
For confirmed bugs or agreed-upon changes, Zotero developers will create new issues in the relevant repositories.
|
||||
|
||||
## Working with Zotero Code
|
||||
|
||||
See [Zotero Source Code](https://www.zotero.org/support/dev/source_code).
|
681
COPYING
Normal file
|
@ -0,0 +1,681 @@
|
|||
Zotero is Copyright © 2018 Corporation for Digital Scholarship,
|
||||
Vienna, Virginia, USA http://digitalscholar.org
|
||||
|
||||
Copyright © 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
Roy Rosenzweig Center for History and New Media, George Mason University,
|
||||
Fairfax, Virginia, USA http://zotero.org
|
||||
|
||||
The Corporation for Digital Scholarship 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 the Corporation for Digital Scholarship.
|
||||
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
|
||||
======
|
||||
[![CI](https://github.com/zotero/zotero/actions/workflows/ci.yml/badge.svg)](https://github.com/zotero/zotero/actions/workflows/ci.yml)
|
||||
|
||||
[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).
|
87
chrome.manifest
Normal file
|
@ -0,0 +1,87 @@
|
|||
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
|
||||
|
||||
content zotero-platform-version chrome/content/zotero-platform/default-version/
|
||||
# Big Sur and later show up as 10.16 when linked against 10.11
|
||||
# (Usually: https://forums.zotero.org/discussion/98406/zotero-will-not-open-mac-os-monterey)
|
||||
content zotero-platform-version chrome/content/zotero-platform/mac-big-sur/ os=Darwin osversion>=10.16
|
||||
#content zotero-platform-version chrome/content/zotero-platform/mac-big-sur/ os=Darwin
|
||||
|
||||
resource zotero resource/
|
||||
|
||||
# Keep in sync with locale.js and zotero-standalone-build:assets/multilocale.txt
|
||||
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 br chrome/locale/br/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 en-GB chrome/locale/en-GB/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
|
||||
|
||||
style chrome://browser/content/browser.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}
|
||||
|
||||
# Scaffold
|
||||
content scaffold chrome/content/scaffold/
|
||||
locale scaffold en-US chrome/locale/en-US/scaffold/
|
||||
skin scaffold default chrome/skin/default/scaffold/
|
88
chrome/content/scaffold/load.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
***** 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 Scaffold_Load = new function() {
|
||||
this.onLoad = Zotero.Promise.coroutine(function* () {
|
||||
var listitem, translator, listcell, set;
|
||||
var listbox = document.getElementById("listbox");
|
||||
|
||||
listbox.addEventListener('dblclick', () => {
|
||||
var translatorID = document.getElementById("listbox").selectedItem.getUserData("zotero-id");
|
||||
if (!translatorID) return;
|
||||
this.accept();
|
||||
window.close();
|
||||
});
|
||||
|
||||
var translators = {};
|
||||
|
||||
// Get the matching translators
|
||||
var translatorProvider = window.arguments[0].translatorProvider;
|
||||
var url = window.arguments[0].url;
|
||||
var rootUrl = window.arguments[0].rootUrl
|
||||
url = Zotero.Proxies.proxyToProper(url);
|
||||
translators["Matching Translators"] = (yield translatorProvider.getWebTranslatorsForLocation(url, rootUrl))[0];
|
||||
translators["Web Translators"] = (yield translatorProvider.getAllForType("web"))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
translators["Import Translators"] = (yield translatorProvider.getAllForType("import"))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
translators["Export Translators"] = (yield translatorProvider.getAllForType("export"))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
translators["Search Translators"] = (yield translatorProvider.getAllForType("search"))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
for (set in translators) {
|
||||
// Make a separator
|
||||
listitem = document.createElement("listitem");
|
||||
listitem.setAttribute("disabled", true);
|
||||
listitem.setAttribute("label", set);
|
||||
listbox.appendChild(listitem);
|
||||
for (var j=0; j<translators[set].length; j++) {
|
||||
var translator = translators[set][j];
|
||||
listitem = document.createElement("listitem");
|
||||
// set label for type-to-find functionality. This is not displayed.
|
||||
listitem.setAttribute("label", translator.label);
|
||||
// And the ID goes in DOM user data
|
||||
listitem.setUserData("zotero-id", translator.translatorID, null);
|
||||
|
||||
listcell = document.createElement("listcell");
|
||||
listcell.setAttribute("label", translator.label);
|
||||
listitem.appendChild(listcell);
|
||||
listcell = document.createElement("listcell");
|
||||
listcell.setAttribute("label", translator.creator);
|
||||
listitem.appendChild(listcell);
|
||||
|
||||
listbox.appendChild(listitem);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.accept = function () {
|
||||
var translatorID = document.getElementById("listbox").selectedItem.getUserData("zotero-id");
|
||||
var translator = window.arguments[0].translatorProvider.get(translatorID);
|
||||
|
||||
Zotero.debug(translatorID);
|
||||
window.arguments[0].dataOut = translator;
|
||||
}
|
||||
}
|
48
chrome/content/scaffold/load.xul
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?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://scaffold/skin/scaffold.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://scaffold/locale/scaffold.dtd">
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&scaffold.load.title;" width="400" height="330" buttons="cancel,accept"
|
||||
ondialogaccept="Scaffold_Load.accept()" onload="Scaffold_Load.onLoad()"
|
||||
id="scaffold-load">
|
||||
|
||||
<script src="chrome://zotero/content/include.js"/>
|
||||
<script src="load.js"/>
|
||||
|
||||
<listbox id="listbox" flex="1">
|
||||
<listhead>
|
||||
<listheader label="&scaffold.load.label.label;"/>
|
||||
<listheader label="&scaffold.load.creator.label;"/>
|
||||
</listhead>
|
||||
<listcols>
|
||||
<listcol flex="1"/>
|
||||
<listcol width="130"/>
|
||||
</listcols>
|
||||
</listbox>
|
||||
</dialog>
|
64
chrome/content/scaffold/monaco/monaco.html
Normal file
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Monaco</title>
|
||||
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container" style="width: 100%; height: 100%"></div>
|
||||
|
||||
<script src="resource://zotero/vs/loader.js"></script>
|
||||
<script>
|
||||
var container = document.getElementById('container');
|
||||
var editor, globalEditor;
|
||||
|
||||
require.config({ paths: { vs: 'resource://zotero/vs' } });
|
||||
|
||||
let proxy = URL.createObjectURL(
|
||||
new Blob(
|
||||
[`
|
||||
self.MonacoEnvironment = {
|
||||
baseUrl: 'resource://zotero/'
|
||||
};
|
||||
importScripts('resource://zotero/vs/base/worker/workerMain.js');
|
||||
`],
|
||||
{ type: "text/javascript" }
|
||||
)
|
||||
);
|
||||
window.MonacoEnvironment = { getWorkerUrl: () => proxy };
|
||||
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
globalEditor = monaco;
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
||||
target: monaco.languages.typescript.ScriptTarget.ES6,
|
||||
allowNonTsExtensions: true // needed for peeking definitions from in-memory models to work
|
||||
});
|
||||
|
||||
editor = monaco.editor.create(container, {
|
||||
theme: 'vs-dark',
|
||||
language: 'javascript',
|
||||
scrollBeyondLastLine: false,
|
||||
minimap: { enabled: false }
|
||||
});
|
||||
|
||||
window.onresize = function () {
|
||||
editor.layout();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
2304
chrome/content/scaffold/scaffold.js
Normal file
416
chrome/content/scaffold/scaffold.xul
Normal file
|
@ -0,0 +1,416 @@
|
|||
<?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://scaffold/skin/scaffold.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-platform-version/content/style.css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/zotero-react-client.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://zotero/content/containers/containers.xul"?>
|
||||
<?xul-overlay href="chrome://zotero/content/standalone/editMenuOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://zotero-platform/content/standalone/menuOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
|
||||
<!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" > %textcontextDTD;
|
||||
<!ENTITY % standaloneDTD SYSTEM "chrome://zotero/locale/standalone.dtd" > %standaloneDTD;
|
||||
<!ENTITY % editMenuOverlayDTD SYSTEM "chrome://zotero/locale/mozilla/editMenuOverlay.dtd" > %editMenuOverlayDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > %brandDTD;
|
||||
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd"> %zoteroDTD;
|
||||
<!ENTITY % scaffoldDTD SYSTEM "chrome://scaffold/locale/scaffold.dtd"> %scaffoldDTD;
|
||||
]>
|
||||
|
||||
<window id="scaffold" width="800" height="600" minheight="600" persist="screenX screenY width height"
|
||||
title="Scaffold"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="chrome://zotero/content/include.js"/>
|
||||
<script src="chrome://zotero/content/xpcom/translate/testTranslators/translatorTester.js"/>
|
||||
<script src="translators.js"/>
|
||||
<script src="scaffold.js"/>
|
||||
|
||||
<script src="chrome://global/content/globalOverlay.js"/>
|
||||
<script src="chrome://global/content/contentAreaUtils.js"/>
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
<command id="cmd_quitApplication" oncommand="goQuitApplication();"/>
|
||||
<command id="cmd_close" oncommand="window.close();"/>
|
||||
|
||||
<command id="cmd_undo" oncommand="Scaffold.trigger('undo', 'cmd_undo')"/>
|
||||
<command id="cmd_redo" oncommand="Scaffold.trigger('redo', 'cmd_redo')"/>
|
||||
<command id="cmd_find" oncommand="Scaffold.trigger('actions.find', 'cmd_find')"/>
|
||||
<command id="cmd_selectAll" oncommand="Scaffold.trigger('editor.selectAll', 'cmd_selectAll')"/>
|
||||
|
||||
<command id="cmd_new" oncommand="Scaffold.newTranslator()"/>
|
||||
<command id="cmd_load" oncommand="Scaffold.load()" disabled="true"/>
|
||||
<command id="cmd_run_translator_or_tests" oncommand="Scaffold.runTranslatorOrTests()"/>
|
||||
<command id="cmd_run_detect" oncommand="Scaffold.run('detect')"/>
|
||||
<command id="cmd_save" oncommand="Scaffold.save()"/>
|
||||
<command id="cmd_save_to_zotero" oncommand="Scaffold.save(true)"/>
|
||||
|
||||
<command id="cmd_increase_font_size" oncommand="Scaffold.increaseFontSize()"/>
|
||||
<command id="cmd_decrease_font_size" oncommand="Scaffold.decreaseFontSize()"/>
|
||||
<command id="cmd_restore_font_size" oncommand="Scaffold.setFontSize(11)"/>
|
||||
|
||||
<commandset id="editMenuCommands"/>
|
||||
</commandset>
|
||||
|
||||
<keyset>
|
||||
<key id="new" modifiers="accel" key="N" command="cmd_new"/>
|
||||
<key id="load" modifiers="accel" key="O" command="cmd_load"/>
|
||||
<key id="run-do-web" modifiers="accel" key="R" command="cmd_run_translator_or_tests"/>
|
||||
<key id="detect-web" modifiers="accel" key="T" command="cmd_run_detect"/>
|
||||
<key id="save" modifiers="accel" key="S" command="cmd_save"/>
|
||||
<key id="save-to-zotero" modifiers="accel alt" key="S" command="cmd_save"/>
|
||||
<key id="increase-font-size" modifiers="accel" key="+" command="cmd_increase_font_size"/>
|
||||
<key id="increase-font-size" modifiers="accel" key="=" command="cmd_increase_font_size"/>
|
||||
<key id="decrease-font-size" modifiers="accel" key="-" command="cmd_decrease_font_size"/>
|
||||
<key id="restore-font-size" modifiers="accel" key="0" command="cmd_restore_font_size"/>
|
||||
|
||||
<key modifiers="accel" key="1" oncommand="Scaffold.showTabNumbered(1)"/>
|
||||
<key modifiers="accel" key="2" oncommand="Scaffold.showTabNumbered(2)"/>
|
||||
<key modifiers="accel" key="3" oncommand="Scaffold.showTabNumbered(3)"/>
|
||||
<key modifiers="accel" key="4" oncommand="Scaffold.showTabNumbered(4)"/>
|
||||
<key modifiers="accel" key="5" oncommand="Scaffold.showTabNumbered(5)"/>
|
||||
<key modifiers="accel" key="6" oncommand="Scaffold.showTabNumbered(6)"/>
|
||||
<key modifiers="accel" key="7" oncommand="Scaffold.showTabNumbered(7)"/>
|
||||
<key modifiers="accel" key="8" oncommand="Scaffold.showTabNumbered(8)"/>
|
||||
<key modifiers="accel" key="9" oncommand="Scaffold.showTabNumbered(9)"/>
|
||||
</keyset>
|
||||
|
||||
<keyset id="editMenuKeys"/>
|
||||
|
||||
<popupset>
|
||||
<menupopup id="testing-context-menue">
|
||||
<menuitem label="&scaffold.testing.copyToClipboard;" tooltiptext="Copy the URL or data for the current test to the clipboard" oncommand="Scaffold.copyToClipboard()"/>
|
||||
<menuitem id="testing_editImport" label="&scaffold.testing.edit;" tooltiptext="Edit the input data for the current test" oncommand="Scaffold.editImportFromTest()"/>
|
||||
<menu id="testing_openURL" label="&scaffold.testing.openUrl;">
|
||||
<menupopup>
|
||||
<menuitem label="&scaffold.testing.openUrl.internally;" tooltiptext="Open the URL for the current test in the Scaffold browser" oncommand="Scaffold.openURL(false)"/>
|
||||
<menuitem label="&scaffold.testing.openUrl.externally;" tooltiptext="Open the URL for the current test in your default browser" oncommand="Scaffold.openURL(true)"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
<broadcasterset>
|
||||
<broadcaster id="code-tab-only" disabled="true"/>
|
||||
<broadcaster id="validate-tests"/>
|
||||
</broadcasterset>
|
||||
|
||||
<vbox flex="1" id="scaffold-pane">
|
||||
|
||||
<menubar id="mb">
|
||||
<menu id="mb-file" label="&fileMenu.label;" accesskey="&fileMenu.accesskey;">
|
||||
<menupopup id="mb-file-popup">
|
||||
<menuitem id="mb-file-new" label="&scaffold.menu.new;" key="new" command="cmd_new"/>
|
||||
<menuitem id="mb-file-load" label="&scaffold.menu.open;" key="load" command="cmd_load"/>
|
||||
<menuitem id="mb-file-setTranslatorsDirectory" label="&scaffold.menu.setTranslatorsDirectory;" oncommand="Scaffold.promptForTranslatorsDirectory()"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="mb-file-save" label="&scaffold.toolbar.save.label;" key="save" command="cmd_save"/>
|
||||
<menuitem id="mb-file-saveToZotero" label="&scaffold.toolbar.saveToZotero.label;" key="save-to-zotero" command="cmd_save_to_zotero"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="mb-file-runDetect" label="&scaffold.menu.runDetect;" key="detect-web" command="cmd_run_detect"/>
|
||||
<menuitem id="mb-file-runDo" label="&scaffold.menu.runDo;" key="run-do-web" command="cmd_run_translator_or_tests"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_close" label="&closeCmd.label;" key="key_close" accesskey="&closeCmd.accesskey;" command="cmd_close"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="menu_edit">
|
||||
<menupopup id="menu_EditPopup">
|
||||
<menuitem id="menu_undo" command="cmd_undo"/>
|
||||
<menuitem id="menu_redo" command="cmd_redo"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_cut"/>
|
||||
<menuitem id="menu_copy"/>
|
||||
<menuitem id="menu_paste"/>
|
||||
<menuitem id="menu_delete"/>
|
||||
<menuseparator class="menu-type-library"/>
|
||||
<menuitem id="menu_selectAll" class="menu-type-library" command="cmd_selectAll"/>
|
||||
<menuseparator class="menu-type-library"/>
|
||||
<menuitem id="menu_find" class="menu-type-library" command="cmd_find"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="mb-view" label="&viewMenu.label;">
|
||||
<menupopup id="mb-view-popup">
|
||||
<menu id="mb-font-size-fields" label="&fontSize.label;">
|
||||
<menupopup id="mb-help-fields-popup">
|
||||
<menuitem id="mb-view-biggerFont" label="&zotero.general.bigger;" key="increase-font-size" command="cmd_increase_font_size"/>
|
||||
<menuitem id="mb-view-smallerFont" label="&zotero.general.smaller;" key="decrease-font-size" command="cmd_decrease_font_size"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="mb-view-restoreFont" label="&zotero.general.reset;" key="restore-font-size" command="restore-font-size"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="toolsMenu" label="&toolsMenu.label;" accesskey="&toolsMenu.accesskey;">
|
||||
<menupopup id="menu_ToolsPopup">
|
||||
<menu id="menu_template"
|
||||
label="&scaffold.menu.template;"
|
||||
observes="code-tab-only">
|
||||
<menupopup>
|
||||
<menuitem label="&scaffold.toolbar.template.newWeb.label;" oncommand="Scaffold.addTemplate('newWeb')"/>
|
||||
<menu label="&scaffold.toolbar.template.scrape.label;">
|
||||
<menupopup id="menu_template_scrapePopup">
|
||||
<menuitem id="tb-template-scrape-em" label="Embedded Metadata" oncommand="Scaffold.addTemplate('scrapeEM')"/>
|
||||
<menuitem id="tb-template-scrape-ris" label="RIS" oncommand="Scaffold.addTemplate('scrapeRIS')"/>
|
||||
<menuitem id="tb-template-scrape-bibtex" label="BibTeX" oncommand="Scaffold.addTemplate('scrapeBibTeX')"/>
|
||||
<menuitem id="tb-template-scrape-marc" label="MARC" oncommand="Scaffold.addTemplate('scrapeMARC')"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<menu id="linter-menu"
|
||||
label="&scaffold.menu.linter;"
|
||||
onpopupshowing="Scaffold.populateLinterMenu()">
|
||||
<menupopup>
|
||||
<menuitem id="menu_eslintStatus" disabled="true"/>
|
||||
<menuitem id="menu_toggleESLint" oncommand="Scaffold.toggleESLint()"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="windowMenu"
|
||||
label="&windowMenu.label;"
|
||||
onpopupshowing="macWindowMenuDidShow();"
|
||||
onpopuphidden="macWindowMenuDidHide();">
|
||||
</menu>
|
||||
|
||||
<menu id="helpMenu" label="&helpMenu.label;" accesskey="&helpMenu.accesskey;">
|
||||
<menupopup id="mb-help-popup">
|
||||
<menuitem id="mb-help-types" label="&scaffold.toolbar.template.itemTypes.label;" oncommand="Scaffold.addTemplate('templateAllTypes')"/>
|
||||
<menu id="mb-help-fields" label="&scaffold.toolbar.template.newItem.label;">
|
||||
<menupopup id="mb-help-fields-popup">
|
||||
<menuitem id="mb-help-fields-book" label="book" oncommand="Scaffold.addTemplate('templateNewItem', 'book')"/>
|
||||
<menuitem id="mb-help-fields-booksection" label="bookSection" oncommand="Scaffold.addTemplate('templateNewItem', 'bookSection')"/>
|
||||
<menuitem id="mb-help-fields-conferencepaper" label="conferencePaper" oncommand="Scaffold.addTemplate('templateNewItem', 'conferencePaper')"/>
|
||||
<menuitem id="mb-help-fields-journalarticle" label="journalArticle" oncommand="Scaffold.addTemplate('templateNewItem', 'journalArticle')"/>
|
||||
<menuitem id="mb-help-fields-magazinearticle" label="magazineArticle" oncommand="Scaffold.addTemplate('templateNewItem', 'magazineArticle')"/>
|
||||
<menuitem id="mb-help-fields-newspaperarticle" label="newspaperArticle" oncommand="Scaffold.addTemplate('templateNewItem', 'newspaperArticle')"/>
|
||||
<menu id="mb-help-fields-more" label="&scaffold.toolbar.template.more.label;">
|
||||
<menupopup id="mb-help-fields-more-popup">
|
||||
<!-- This will be filled on load with all other item types -->
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
||||
<toolbar id="zotero-toolbar" class="toolbar toolbar-primary">
|
||||
<hbox id="scaffold-toolbar" align="center">
|
||||
<toolbarbutton id="tb-load" tooltiptext="&scaffold.toolbar.load.label;" command="cmd_load" class="zotero-tb-button" />
|
||||
<toolbarbutton id="tb-save" tooltiptext="&scaffold.toolbar.save.label;" oncommand="Scaffold.save()" class="zotero-tb-button" />
|
||||
<toolbarbutton id="tb-saveToZotero" tooltiptext="&scaffold.toolbar.saveToZotero.label;" oncommand="Scaffold.save(true)" class="zotero-tb-button" />
|
||||
<toolbarseparator/>
|
||||
<toolbarbutton id="tb-detect" tooltiptext="&scaffold.toolbar.detect.label;" oncommand="Scaffold.run('detect')" class="zotero-tb-button" />
|
||||
<toolbarbutton id="tb-do" tooltiptext="&scaffold.toolbar.do.label;" oncommand="Scaffold.run('do')" class="zotero-tb-button" />
|
||||
<toolbarseparator/>
|
||||
<toolbarbutton id="tb-template" observes="code-tab-only" tooltiptext="&scaffold.toolbar.template.label;" class="zotero-tb-button" type="menu">
|
||||
<menupopup>
|
||||
<menuitem label="&scaffold.toolbar.template.newWeb.label;" oncommand="Scaffold.addTemplate('newWeb')"/>
|
||||
<menu label="&scaffold.toolbar.template.scrape.label;">
|
||||
<menupopup id="menu_template_scrapePopup">
|
||||
<menuitem id="tb-template-scrape-em" label="Embedded Metadata" oncommand="Scaffold.addTemplate('scrapeEM')"/>
|
||||
<menuitem id="tb-template-scrape-ris" label="RIS" oncommand="Scaffold.addTemplate('scrapeRIS')"/>
|
||||
<menuitem id="tb-template-scrape-bibtex" label="BibTeX" oncommand="Scaffold.addTemplate('scrapeBibTeX')"/>
|
||||
<menuitem id="tb-template-scrape-marc" label="MARC" oncommand="Scaffold.addTemplate('scrapeMARC')"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
</hbox>
|
||||
</toolbar>
|
||||
<hbox flex="1">
|
||||
<tabbox id="left-tabbox" flex="2" width="300">
|
||||
<tabs id="tabs" onselect="Scaffold.handleTabSelect(event)">
|
||||
<tab id="tab-metadata" label="&scaffold.tabs.metadata.label;"/>
|
||||
<tab id="tab-code" label="&scaffold.tabs.code.label;"/>
|
||||
<tab id="tab-tests" label="&scaffold.tabs.tests.label;"/>
|
||||
<tab id="tab-browser" label="Browser"/>
|
||||
<tab id="tab-import" label="&scaffold.tabs.import.label;"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel flex="1" id="tabpanel-metadata">
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.translatorID.label;" control="textbox-translatorID"/>
|
||||
<hbox>
|
||||
<textbox id="textbox-translatorID" flex="1"/>
|
||||
<button label="&scaffold.metadata.translatorID.generate;" oncommand="Scaffold.generateTranslatorID()"/>
|
||||
</hbox>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.label.label;" control="textbox-label"/>
|
||||
<textbox id="textbox-label" flex="1" value="&scaffold.metadata.label.default;"/>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.creator.label;" control="textbox-creator"/>
|
||||
<textbox id="textbox-creator" flex="1"/>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.target.label;" control="textbox-target"/>
|
||||
<hbox>
|
||||
<textbox id="textbox-target" flex="1"/>
|
||||
<button label="&scaffold.metadata.target.testRegex;" oncommand="Scaffold.logTargetRegex()"/>
|
||||
</hbox>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.targetAll.label;" control="textbox-target-all" style="display: none"/>
|
||||
<textbox id="textbox-target-all" flex="1" style="display: none"/>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.configOptions.label;" control="textbox-configOptions"/>
|
||||
<textbox id="textbox-configOptions" flex="1"/>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.displayOptions.label;" control="textbox-displayOptions"/>
|
||||
<textbox id="textbox-displayOptions" flex="1"/>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.minVersion.label;" control="textbox-minVersion"/>
|
||||
<hbox>
|
||||
<textbox id="textbox-minVersion" flex="1" value="5.0"/>
|
||||
<label class="label-metadata" value="&scaffold.metadata.priority.label;" control="textbox-priority"/>
|
||||
<textbox id="textbox-priority" flex="1" value="&scaffold.metadata.priority.default;"/>
|
||||
</hbox>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.hiddenPrefs.label;" control="textbox-hidden-prefs" style="display: none"/>
|
||||
<textbox id="textbox-hidden-prefs" flex="1" style="display: none"/>
|
||||
</row>
|
||||
|
||||
<row align="center">
|
||||
<label class="label-metadata" value="&scaffold.metadata.translatorType.label;"/>
|
||||
<hbox id="checkboxes-translatorType">
|
||||
<checkbox id="checkbox-import" label="&scaffold.metadata.translatorType.import;"/>
|
||||
<checkbox id="checkbox-export" label="&scaffold.metadata.translatorType.export;"/>
|
||||
<checkbox id="checkbox-web" label="&scaffold.metadata.translatorType.web;" checked="true"/>
|
||||
<checkbox id="checkbox-search" label="&scaffold.metadata.translatorType.search;"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</tabpanel>
|
||||
<tabpanel flex="1" id="tabpanel-code">
|
||||
<vbox flex="1">
|
||||
<iframe src="monaco/monaco.html" id="editor-code" flex="1" onmousedown="this.focus()"/>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel flex="1" id="tabpanel-tests">
|
||||
<vbox flex="1">
|
||||
<vbox flex="1">
|
||||
<hbox flex="1" context="testing-context-menue">
|
||||
<keyset>
|
||||
<key id="key-delete-tests" observes="validate-tests" keycode="VK_BACK" oncommand="Scaffold.deleteSelectedTests()"/>
|
||||
</keyset>
|
||||
|
||||
<listbox id="testing-listbox" observes="validate-tests" flex="1" seltype="multiple" onselect="Scaffold.handleTestSelect(event)">
|
||||
<listhead>
|
||||
<listheader label="&scaffold.testing.input.label;"/>
|
||||
<listheader label="&scaffold.testing.status.label;"/>
|
||||
<listheader label="&scaffold.testing.defer.label;"/>
|
||||
</listhead>
|
||||
<listcols>
|
||||
<listcol flex="1"/>
|
||||
<listcol class="listcol-testMessage"/>
|
||||
<listcol/>
|
||||
</listcols>
|
||||
</listbox>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<button observes="validate-tests" label="&scaffold.testing.delete;" tooltiptext="Delete the selected tests" oncommand="Scaffold.deleteSelectedTests()"/>
|
||||
<button observes="validate-tests" label="&scaffold.testing.run;" tooltiptext="Run the selected tests" oncommand="Scaffold.runSelectedTests()"/>
|
||||
<button observes="validate-tests" label="&scaffold.testing.update;" tooltiptext="Run the selected tests and update the test definitions with the latest data" oncommand="Scaffold.updateSelectedTests()"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<splitter resizeafter="farthest"/>
|
||||
<iframe src="monaco/monaco.html" id="editor-tests" flex="2" onmousedown="this.focus()"/>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel>
|
||||
<vbox flex="1">
|
||||
<hbox align="center">
|
||||
<label control="textbox-tabUrl" value="&scaffold.tabUrl.label;"/>
|
||||
<menulist id="browser-url" editable="true" flex="1">
|
||||
<menupopup></menupopup>
|
||||
</menulist>
|
||||
<button observes="validate-tests" label="&scaffold.testing.create.web;" tooltiptext="Create a new test from the current page" oncommand="Scaffold.saveTestFromCurrent('web')"/>
|
||||
</hbox>
|
||||
|
||||
<browser id="browser" src="about:blank" type="content" flex="1"></browser>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
<tabpanel flex="1" id="tabpanel-import">
|
||||
<vbox flex="1">
|
||||
<hbox align="right">
|
||||
<button observes="validate-tests" label="&scaffold.testing.create.import;" tooltiptext="Create a new test from the current import data" oncommand="Scaffold.saveTestFromCurrent('import')" />
|
||||
<button observes="validate-tests" label="&scaffold.testing.create.search;" tooltiptext="Create a new test from the current search data" oncommand="Scaffold.saveTestFromCurrent('search')" />
|
||||
</hbox>
|
||||
<iframe src="monaco/monaco.html" id="editor-import" flex="1" onmousedown="this.focus()"/>
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
<splitter resizeafter="farthest" />
|
||||
|
||||
<vbox id="right-pane" flex="1">
|
||||
|
||||
<hbox id="hbox-testFrame" width="300">
|
||||
<label control="menulist-testFrame" id="label-testFrame" value="&scaffold.testFrame.label;"/>
|
||||
<menulist id="menulist-testFrame"/>
|
||||
</hbox>
|
||||
|
||||
<textbox flex="1" id="output" multiline="true" readonly="true"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</vbox>
|
||||
|
||||
<keyset>
|
||||
<key id="key_close" key="W" modifiers="accel" oncommand="window.close()"/>
|
||||
</keyset>
|
||||
</window>
|
70
chrome/content/scaffold/templates/newWeb.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2022 YOUR_NAME <- TODO
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
// TODO: adjust the logic here
|
||||
if ($$CURSOR$$url.includes('/article/')) {
|
||||
return 'newspaperArticle';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
// TODO: adjust the CSS selector
|
||||
var rows = doc.querySelectorAll('h2 > a.title[href*="/article/"]');
|
||||
for (let row of rows) {
|
||||
// TODO: check and maybe adjust
|
||||
let href = row.href;
|
||||
// TODO: check and maybe adjust
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
// TODO: implement or add a scrape function template
|
||||
}
|
||||
|
20
chrome/content/scaffold/templates/scrapeBibTeX.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
async function scrape(doc, url = doc.location.href) {
|
||||
// TODO adjust the url building
|
||||
let m = url.match(/FId=([\w\d]+)&/);
|
||||
if (m) {
|
||||
// e.g. http://www.fachportal-paedagogik.de/fis_bildung/suche/fis_ausg.html?FId=A18196&lart=BibTeX&Speichern=Speichern&senden_an=+E-Mail-Adresse
|
||||
let bibUrl = '/fis_bildung/suche/fis_ausg.html?FId=' + m[1] + '&lart=BibTeX';
|
||||
let bibText = await requestText(bibUrl);
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator('9cb70025-a888-4a29-a210-93ec52da40d4');
|
||||
translator.setString(bibText);
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
}
|
20
chrome/content/scaffold/templates/scrapeEM.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
async function scrape(doc, url = doc.location.href) {
|
||||
let translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
// TODO adjust if needed:
|
||||
item.section = 'News';
|
||||
item.complete();
|
||||
});
|
||||
|
||||
let em = await translator.getTranslatorObject();
|
||||
em.itemType = 'newspaperArticle';
|
||||
// TODO map additional meta tags here, or delete completely
|
||||
em.addCustomFields({
|
||||
'twitter:description': 'abstractNote'
|
||||
});
|
||||
await em.doWeb(doc, url);
|
||||
}
|
35
chrome/content/scaffold/templates/scrapeMARC.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
async function scrape(doc, url = doc.location.href) {
|
||||
// TODO adjust the selector for the lines here
|
||||
let lines = doc.querySelectorAll('table#marcData tr');
|
||||
|
||||
let translator = Zotero.loadTranslator('import');
|
||||
translator.setTranslator('a6ee60df-1ddc-4aae-bb25-45e0537be973'); // MARC
|
||||
let MARC = await translator.getTranslatorObject();
|
||||
|
||||
let record = new MARC.Record();
|
||||
let item = new Zotero.Item();
|
||||
// ignore the table headings in lines[0]
|
||||
record.leader = text(lines[1], 'td', 4);
|
||||
let fieldTag;
|
||||
for (let line of Array.from(lines).slice(2)) {
|
||||
// multiple lines with same fieldTag do not repeat the tag
|
||||
// i.e. in these cases we will just take same value as before
|
||||
if (text(line, 'td', 0)) {
|
||||
fieldTag = text(line, 'td', 0);
|
||||
}
|
||||
let indicators = text(line, 'td', 1) + text(line, 'td', 2);
|
||||
let fieldContent = '';
|
||||
if (text(line, 'td', 3)) {
|
||||
fieldContent = MARC.subfieldDelimiter + text(line, 'td', 3);
|
||||
}
|
||||
fieldContent += text(line, 'td', 4);
|
||||
|
||||
record.addField(fieldTag, indicators, fieldContent);
|
||||
}
|
||||
|
||||
record.translate(item);
|
||||
|
||||
// possibly clean item further here
|
||||
|
||||
item.complete();
|
||||
}
|
33
chrome/content/scaffold/templates/scrapeRIS.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
async function scrape(doc, url = doc.location.href) {
|
||||
let DOI = url.match(/\/(10\.[^#?]+)/)[1];
|
||||
// TODO adjust the URL here
|
||||
let risURL = `http://citation-needed.services.springer.com/v2/references/${DOI}?format=refman&flavour=citation`;
|
||||
// Z.debug(risURL)
|
||||
|
||||
// TODO adjust this
|
||||
let pdfLink = doc.querySelector('#articlePDF');
|
||||
// Z.debug("pdfURL: " + pdfURL);
|
||||
|
||||
let risText = await requestText(risURL);
|
||||
let translator = Zotero.loadTranslator('import');
|
||||
translator.setTranslator('32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7'); // RIS
|
||||
translator.setString(risText);
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
// TODO tweak some of the output here
|
||||
if (pdfLink) {
|
||||
item.attachments.push({
|
||||
url: pdfLink.href,
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
159
chrome/content/scaffold/translators.js
Normal file
|
@ -0,0 +1,159 @@
|
|||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
var Scaffold_Translators = {
|
||||
// Keep in sync with translator.js
|
||||
TRANSLATOR_TYPES: { import: 1, export: 2, web: 4, search: 8 },
|
||||
|
||||
_provider: null,
|
||||
_translators: new Map(),
|
||||
_translatorFiles: new Map(),
|
||||
_onLoadBeginListener: null,
|
||||
_onLoadCompleteListener: null,
|
||||
|
||||
load: Zotero.serial(async function (reload) {
|
||||
if (this._translators.size && !reload) {
|
||||
Zotero.debug("Scaffold: Translators already loaded");
|
||||
return { numLoaded: 0, numDeleted: 0 };
|
||||
}
|
||||
|
||||
if (this._onLoadBeginListener) this._onLoadBeginListener();
|
||||
|
||||
var t = new Date();
|
||||
var dir = this.getDirectory();
|
||||
var numLoaded = 0;
|
||||
var deletedTranslators = new Set(this._translatorFiles.keys());
|
||||
await Zotero.File.iterateDirectory(dir, async function (entry) {
|
||||
if (entry.isDir || entry.name.startsWith('.') || !entry.name.endsWith('.js')) {
|
||||
return;
|
||||
}
|
||||
|
||||
deletedTranslators.delete(entry.name);
|
||||
|
||||
try {
|
||||
let fmtime;
|
||||
if ('winLastWriteDate' in entry) {
|
||||
fmtime = entry.winLastWriteDate.getTime();
|
||||
}
|
||||
else {
|
||||
fmtime = (await OS.File.stat(entry.path)).lastModificationDate.getTime();
|
||||
}
|
||||
let translatorID = this._translatorFiles.get(entry.name);
|
||||
let loadFile = true;
|
||||
// If translator is already loaded, see if mtime has changed
|
||||
if (translatorID) {
|
||||
let mtime = this._translators.get(translatorID).mtime;
|
||||
if (mtime == fmtime) {
|
||||
loadFile = false;
|
||||
}
|
||||
}
|
||||
if (loadFile) {
|
||||
let translator = await Zotero.Translators.loadFromFile(entry.path);
|
||||
this._translators.set(
|
||||
translator.translatorID,
|
||||
{
|
||||
translator,
|
||||
filename: entry.name,
|
||||
mtime: fmtime,
|
||||
}
|
||||
);
|
||||
this._translatorFiles.set(entry.name, translator.translatorID);
|
||||
numLoaded++;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
Zotero.debug(`Scaffold: Loaded ${numLoaded} ${Zotero.Utilities.pluralize(numLoaded, 'translator')} `
|
||||
+ `in ${new Date() - t} ms`);
|
||||
|
||||
for (let filename of deletedTranslators) {
|
||||
let id = this._translatorFiles.get(filename);
|
||||
let translator = this._translators.get(id);
|
||||
this._translatorFiles.delete(filename);
|
||||
// Filename won't match if translator was renamed
|
||||
if (translator.filename == filename) {
|
||||
this._translators.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._onLoadCompleteListener) this._onLoadCompleteListener();
|
||||
|
||||
return {
|
||||
numLoaded,
|
||||
numDeleted: deletedTranslators.size
|
||||
};
|
||||
}),
|
||||
|
||||
deleteByID: async function (translatorID) {
|
||||
var translator = this._translators.get(translatorID);
|
||||
if (!translator) {
|
||||
Zotero.debug("Scaffold: Can't delete missing translator");
|
||||
return;
|
||||
}
|
||||
await OS.File.delete(OS.Path.join(this.getDirectory(), translator.filename));
|
||||
this._translators.delete(translatorID);
|
||||
this._translatorFiles.delete(translator.filename);
|
||||
},
|
||||
|
||||
getDirectory: function () {
|
||||
return Zotero.Prefs.get('scaffold.translatorsDir');
|
||||
},
|
||||
|
||||
getModifiedTime: function (translatorID) {
|
||||
return this._translators.get(translatorID)?.mtime;
|
||||
},
|
||||
|
||||
getProvider: function () {
|
||||
if (this._provider) {
|
||||
return this._provider;
|
||||
}
|
||||
this._provider = Zotero.Translators.makeTranslatorProvider({
|
||||
get: function (translatorID) {
|
||||
if (!this._translators.size) {
|
||||
throw new Error("Scaffold: Translators not loaded");
|
||||
}
|
||||
var translator = this._translators.get(translatorID);
|
||||
return translator ? translator.translator : false;
|
||||
}.bind(this),
|
||||
|
||||
getCodeForTranslator: async function (translator) {
|
||||
if (translator.code) return translator.code;
|
||||
return Zotero.File.getContentsAsync(translator.path).then(function(code) {
|
||||
if (translator.cacheCode) {
|
||||
// See Translator.init() for cache rules
|
||||
translator.code = code;
|
||||
}
|
||||
return code;
|
||||
});
|
||||
}.bind(this),
|
||||
|
||||
getAllForType: async function (type) {
|
||||
if (!this._translators.size) {
|
||||
await this.load();
|
||||
}
|
||||
return [...this._translators.values()]
|
||||
.map(x => x.translator)
|
||||
.filter(translator => translator.translatorType & this.TRANSLATOR_TYPES[type]);
|
||||
}.bind(this),
|
||||
|
||||
getTranslatorsDirectory: function () {
|
||||
return this.getDirectory();
|
||||
}.bind(this),
|
||||
|
||||
reinit: async function (options = {}) {
|
||||
return this.load(
|
||||
true,
|
||||
options.filenames
|
||||
);
|
||||
}.bind(this)
|
||||
});
|
||||
return this._provider;
|
||||
},
|
||||
|
||||
setLoadListener({ onLoadBegin, onLoadComplete }) {
|
||||
this._onLoadBeginListener = onLoadBegin;
|
||||
this._onLoadCompleteListener = onLoadComplete;
|
||||
}
|
||||
};
|
0
chrome/content/zotero-platform/default-version/style.css
Normal file
17
chrome/content/zotero-platform/mac-big-sur/style.css
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* Use standard tab appearance for item pane tabs */
|
||||
.zotero-view-tabbox > tabs > tab {
|
||||
-moz-appearance: tab;
|
||||
}
|
||||
|
||||
/* Active tab label color in item pane and elsewhere */
|
||||
tabs.zotero-editpane-tabs > tab[visuallyselected="true"][selected="true"] hbox > .tab-text,
|
||||
#zotero-prefs tab[visuallyselected="true"]:not(:-moz-window-inactive),
|
||||
tabs > tab[visuallyselected="true"] hbox > .tab-text {
|
||||
color: black !important;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
/* Quick Format dialog, which is based on window corners, which are different on Big Sur */
|
||||
#quick-format-iframe {
|
||||
margin-top: 2px;
|
||||
}
|
4
chrome/content/zotero-platform/mac/attachmentbox.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
row > label:first-child
|
||||
{
|
||||
color: #7f7f7f;
|
||||
}
|
108
chrome/content/zotero-platform/mac/integration.css
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* Force use of Lucida for Catalina */
|
||||
html > body {
|
||||
font-family: Lucida Grande, Lucida Sans Unicode, Lucida Sans, Geneva, -apple-system, sans-serif !important;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1.6em;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
body[multiline="true"] {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
window.citation-dialog {
|
||||
background: transparent;
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
.citation-dialog.progress-bar .citation-dialog.deck {
|
||||
height: 37px;
|
||||
}
|
||||
|
||||
.citation-dialog.search {
|
||||
background: white;
|
||||
padding: 2px 2px 0 2px;
|
||||
margin: 2.5px 3.5px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
-moz-appearance: none;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.citation-dialog.search:not([multiline="true"]) {
|
||||
height: 32px !important;
|
||||
}
|
||||
|
||||
.citation-dialog.entry {
|
||||
background: -moz-linear-gradient(-90deg, rgb(243,123,119) 0, rgb(180,47,38) 50%, rgb(156,36,27) 50%);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.note-dialog .citation-dialog.entry {
|
||||
background: -moz-linear-gradient(-90deg, rgb(249, 231, 179) 0, rgb(228, 193, 94) 50%, rgb(221, 184, 81) 50%);
|
||||
}
|
||||
|
||||
#zotero-icon {
|
||||
margin: -1px 0 0 4px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
.citation-dialog.bubble {
|
||||
padding: 1px 6px 1px 6px;
|
||||
}
|
9
chrome/content/zotero-platform/mac/itemPane.css
Normal file
|
@ -0,0 +1,9 @@
|
|||
#zotero-feed-item-addTo-button {
|
||||
margin: 5px 6px 3px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
#zotero-feed-item-addTo-button button {
|
||||
margin: 0;
|
||||
-moz-appearance: none;
|
||||
}
|
44
chrome/content/zotero-platform/mac/itembox.css
Normal file
|
@ -0,0 +1,44 @@
|
|||
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;
|
||||
}
|
||||
|
||||
.zotero-focusable:focus {
|
||||
/* At least in Fx60, the color doesn't quite match Monterey's native textbox outline,
|
||||
but it will have to do for now */
|
||||
outline: 2px solid -moz-mac-focusring !important;
|
||||
}
|
||||
|
||||
textbox
|
||||
{
|
||||
margin: -1px 5px -1px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* BEGIN 2X BLOCK -- DO NOT EDIT MANUALLY -- USE 2XIZE */
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
.creator-type-label > image { list-style-image: url('chrome://zotero/skin/mac/arrow-down@2x.png'); }
|
||||
}
|
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;
|
||||
}
|
397
chrome/content/zotero-platform/mac/overlay.css
Normal file
|
@ -0,0 +1,397 @@
|
|||
/* Force use of Lucida for HTML input elements (e.g., Editable) */
|
||||
input {
|
||||
font-family: Lucida Grande, Lucida Sans Unicode, Lucida Sans, Geneva, -apple-system, sans-serif !important;
|
||||
}
|
||||
|
||||
#zotero-items-toolbar[state=collapsed]
|
||||
{
|
||||
margin-left: -8px !important;
|
||||
}
|
||||
|
||||
#zotero-pane toolbarseparator {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-stop .toolbarbutton-icon,
|
||||
#zotero-tb-sync-error .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.zotero-tb-button > .toolbarbutton-icon {
|
||||
max-width: 31px;
|
||||
}
|
||||
|
||||
.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/auto 24px no-repeat;
|
||||
}
|
||||
|
||||
.zotero-tb-button[type=menu] {
|
||||
-moz-padding-end: 8px !important;
|
||||
}
|
||||
|
||||
.zotero-tb-button > .toolbarbutton-icon {
|
||||
background: url("chrome://zotero/skin/mac/menubutton-start.png") left center/auto 24px no-repeat;
|
||||
padding: 4px 4px 4px 11px;
|
||||
}
|
||||
|
||||
/* For menu buttons, decrease left padding by 1px */
|
||||
.zotero-tb-button[type=menu] > .toolbarbutton-icon {
|
||||
-moz-padding-start: 9px;
|
||||
max-width: 29px;
|
||||
}
|
||||
|
||||
#zotero-collections-toolbar {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.zotero-tb-button:-moz-window-inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.zotero-tb-button:-moz-window-inactive > .toolbarbutton-icon {
|
||||
background: url("chrome://zotero/skin/mac/menubutton-start-inactive-window.png") left center/auto 24px no-repeat;
|
||||
}
|
||||
|
||||
/* Use a darker background when inactive so the button itself doesn't get too dark at 50% */
|
||||
.zotero-tb-button:-moz-window-inactive,
|
||||
.zotero-tb-button:-moz-window-inactive:first-child,
|
||||
.zotero-tb-button:-moz-window-inactive:last-child {
|
||||
background: url("chrome://zotero/skin/mac/menubutton-end-inactive-window.png") right center/auto 24px no-repeat;
|
||||
}
|
||||
|
||||
.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/auto 24px no-repeat;
|
||||
}
|
||||
|
||||
.zotero-tb-button > menupopup {
|
||||
-moz-margin-start: 2px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button {
|
||||
margin: -6px 0 -6px -16px;
|
||||
padding: 6px 0 6px 15px;
|
||||
}
|
||||
|
||||
#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/auto 24px 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-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-box description {
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
.zotero-view-tabbox > tabpanels {
|
||||
margin: 12px 0 0 0;
|
||||
padding: 0;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.zotero-editpane-tabs {
|
||||
-moz-appearance: none;
|
||||
background: -moz-linear-gradient(top, #ededed, #cccccc);
|
||||
border-style: solid;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: #bdbdbd;
|
||||
padding: 2px 0 2px 0;
|
||||
}
|
||||
|
||||
.zotero-editpane-tabs > tab > hbox {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.zotero-editpane-tabs > tab > hbox > .tab-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.zotero-editpane-tabs > tab {
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
-moz-appearance: toolbarbutton;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 3px 1px 3px 1px;
|
||||
}
|
||||
|
||||
.zotero-editpane-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-editpane-tabs > tab:last-of-type > hbox .tab-text {
|
||||
margin-left: 9px !important;
|
||||
margin-right: 9px !important;
|
||||
}
|
||||
|
||||
.zotero-editpane-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:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed])[orient=horizontal],
|
||||
#zotero-context-splitter:not([state=collapsed])[orient=horizontal]
|
||||
{
|
||||
-moz-appearance: none;
|
||||
border-inline-start: 1px solid #bdbdbd;
|
||||
margin-inline-end: -4px;
|
||||
width: 5px !important;
|
||||
min-width: 5px;
|
||||
/* Create a separate stacking context to be on top */
|
||||
opacity: 0.99;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#zotero-items-splitter[orient=vertical],
|
||||
#zotero-context-splitter-stacked
|
||||
{
|
||||
-moz-border-start: none !important;
|
||||
-moz-border-end: none !important;
|
||||
background-color: #bdbdbd !important;
|
||||
max-height: 1px !important;
|
||||
min-height: 1px !important;
|
||||
height: 1px !important;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-items-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-context-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) > grippy
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed],
|
||||
#zotero-items-splitter[state=collapsed],
|
||||
#zotero-context-splitter[state=collapsed],
|
||||
#zotero-context-splitter-stacked[state=collapsed]
|
||||
{
|
||||
border: 0 solid #d6d6d6 !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed],
|
||||
#zotero-items-splitter[state=collapsed][orient=horizontal],
|
||||
#zotero-context-splitter[state=collapsed][orient=horizontal]
|
||||
{
|
||||
background-image: url("chrome://zotero/skin/mac/vsplitter.png");
|
||||
background-repeat: repeat-y;
|
||||
max-width: 8px !important;
|
||||
min-width: 8px !important;
|
||||
width: 8px !important;
|
||||
}
|
||||
|
||||
#zotero-items-splitter[state=collapsed][orient=vertical],
|
||||
#zotero-context-splitter-stacked[state=collapsed][orient=vertical]
|
||||
{
|
||||
background-image: url("chrome://zotero/skin/mac/hsplitter.png");
|
||||
background-repeat: repeat-x;
|
||||
max-height: 8px !important;
|
||||
min-height: 8px !important;
|
||||
height: 8px !important;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed] {
|
||||
border-right-width: 1px !important;
|
||||
}
|
||||
|
||||
#zotero-items-splitter[state=collapsed],
|
||||
#zotero-context-splitter[state=collapsed],
|
||||
#zotero-context-splitter-stacked[state=collapsed]
|
||||
{
|
||||
border-left-width: 1px !important;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter[state=collapsed] > grippy,
|
||||
#zotero-items-splitter[state=collapsed] > grippy,
|
||||
#zotero-context-splitter[state=collapsed] > grippy,
|
||||
#zotero-context-splitter-stacked[state=collapsed] > grippy
|
||||
{
|
||||
-moz-appearance: none;
|
||||
background: url(chrome://zotero/skin/mac/vgrippy.png) center/auto 8px 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: url(chrome://zotero/skin/mac/hgrippy.png) center/auto 8px no-repeat;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
#zotero-tags-splitter > grippy:hover,
|
||||
#zotero-collections-splitter > grippy:hover,
|
||||
#zotero-items-splitter > grippy:hover,
|
||||
#zotero-context-splitter > grippy:hover,
|
||||
#zotero-context-splitter-stacked > grippy:hover
|
||||
{
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
#zotero-context-toolbar-extension {
|
||||
/* To cover #zotero-context-splitter 1px border */
|
||||
margin-inline-start: -1px;
|
||||
}
|
||||
|
||||
/* 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');
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
/* BEGIN 2X BLOCK -- DO NOT EDIT MANUALLY -- USE 2XIZE */
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
.zotero-tb-button,.zotero-tb-button:first-child,.zotero-tb-button:last-child { background: url("chrome://zotero/skin/mac/menubutton-end@2x.png") right center/auto 24px no-repeat; }
|
||||
.zotero-tb-button > .toolbarbutton-icon { background: url("chrome://zotero/skin/mac/menubutton-start@2x.png") left center/auto 24px no-repeat; }
|
||||
.zotero-tb-button:-moz-window-inactive > .toolbarbutton-icon { background: url("chrome://zotero/skin/mac/menubutton-start-inactive-window@2x.png") left center/auto 24px no-repeat; }
|
||||
.zotero-tb-button:-moz-window-inactive,.zotero-tb-button:-moz-window-inactive:first-child,.zotero-tb-button:-moz-window-inactive:last-child { background: url("chrome://zotero/skin/mac/menubutton-end-inactive-window@2x.png") right center/auto 24px no-repeat; }
|
||||
.zotero-tb-button[open="true"],.zotero-tb-button:not([disabled="true"]):hover:active { background: url("chrome://zotero/skin/mac/menubutton-end-pressed@2x.png") right center/auto 24px no-repeat; }
|
||||
.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@2x.png") left center/auto 24px no-repeat; }
|
||||
#zotero-collections-splitter[state=collapsed] > grippy, #zotero-items-splitter[state=collapsed] > grippy { background: url(chrome://zotero/skin/mac/vgrippy@2x.png) center/auto 8px no-repeat; }
|
||||
#zotero-tags-splitter > grippy { background: url(chrome://zotero/skin/mac/hgrippy@2x.png) center/auto 8px no-repeat; }
|
||||
#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'); }
|
||||
}
|
BIN
chrome/content/zotero-platform/mac/panebutton-active.png
Normal file
After Width: | Height: | Size: 400 B |
BIN
chrome/content/zotero-platform/mac/panebutton-inactive.png
Normal file
After Width: | Height: | Size: 257 B |
138
chrome/content/zotero-platform/mac/preferences.css
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
prefwindow,
|
||||
prefwindow:root /* override :root from above */ {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-mac.xml#prefwindow");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
prefpane {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-mac.xml#prefpane");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
prefwindow > .paneDeckContainer {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
prefpane > .content-box {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > .paneDeckContainer {
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > prefpane > .content-box {
|
||||
-moz-box-flex: 1;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
preferences {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-mac.xml#preferences");
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
preference {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-mac.xml#preference");
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
radio[pane] {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-mac.xml#panebutton") !important;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
prefwindow[chromehidden~="toolbar"] .chromeclass-toolbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
prefwindow {
|
||||
padding: 0;
|
||||
font: -moz-dialog !important;
|
||||
|
||||
-moz-appearance: dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
prefpane {
|
||||
padding: 12px 12px 0 12px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > prefpane {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.prefWindow-dlgbuttons {
|
||||
margin: 0 12px 12px;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
.paneSelector {
|
||||
font: message-box;
|
||||
padding: 1px 4px;
|
||||
-moz-appearance: toolbar;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
radio[pane] {
|
||||
border: solid transparent;
|
||||
border-width: 0 2px;
|
||||
padding: 5px 4px 3px;
|
||||
margin: 0;
|
||||
-moz-appearance: none;
|
||||
text-shadow: rgba(255, 255, 255, 0.4) 0 1px;
|
||||
}
|
||||
|
||||
radio[pane]:active:hover {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
radio[pane]:active:hover > .paneButtonIcon {
|
||||
filter: brightness(0.55);
|
||||
}
|
||||
|
||||
radio[pane][selected="true"] {
|
||||
-moz-border-image: url("chrome://zotero-platform/content/panebutton-active.png") 0 2 fill repeat stretch;
|
||||
}
|
||||
|
||||
radio[pane][selected="true"]:-moz-window-inactive {
|
||||
-moz-border-image: url("chrome://zotero-platform/content/panebutton-inactive.png") 0 2 fill repeat stretch;
|
||||
}
|
||||
|
||||
.paneButtonLabel {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
groupbox {
|
||||
padding: 5px 1px 1px;
|
||||
padding-inline-start: 0;
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
.groupbox-title {
|
||||
border-bottom: #b5b5b5 1px solid;
|
||||
}
|
||||
|
||||
.groupbox-body {
|
||||
-moz-appearance: groupbox;
|
||||
padding: 8px 8px 3px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-inline-start: 4px;
|
||||
padding-bottom: 1px;
|
||||
font: caption;
|
||||
}
|
||||
|
||||
/* !important is needed to override label in global.css */
|
||||
.caption-text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
margin-inline-start: 1px !important;
|
||||
}
|
136
chrome/content/zotero-platform/mac/standalone/menuOverlay.xul
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?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;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://zotero/locale/mozilla/browser.dtd"> %browserDTD;
|
||||
]>
|
||||
<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"/>
|
||||
<script>
|
||||
function openPrefs() {
|
||||
var Zotero = Components.classes['@zotero.org/Zotero;1']
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
Zotero.Utilities.Internal.openPreferences();
|
||||
}
|
||||
</script>
|
||||
|
||||
<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="openPrefs()"/>
|
||||
<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="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-collection@2x.png
Normal file
After Width: | Height: | Size: 589 B |
BIN
chrome/content/zotero-platform/mac/treesource-search.png
Normal file
After Width: | Height: | Size: 549 B |
BIN
chrome/content/zotero-platform/mac/treesource-search@2x.png
Normal file
After Width: | Height: | Size: 1 KiB |
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 |
7
chrome/content/zotero-platform/mac/zotero.css
Normal file
|
@ -0,0 +1,7 @@
|
|||
.zotero-advanced-options > .zotero-advanced-options-label > dropmarker {
|
||||
transform: rotate(270deg) translateX(4px);
|
||||
}
|
||||
|
||||
.zotero-advanced-options[state="open"] > .zotero-advanced-options-label > dropmarker {
|
||||
transform: translateX(4px);
|
||||
}
|
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;
|
||||
}
|
||||
|
||||
.citation-dialog.search:not([multiline="true"]) {
|
||||
height: 29px !important;
|
||||
}
|
||||
|
||||
.citation-dialog.search {
|
||||
background: white;
|
||||
padding: 0 2px 0 0;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
window.citation-dialog {
|
||||
-moz-appearance: none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#zotero-icon {
|
||||
margin: 0 0 0 2px;
|
||||
-moz-appearance: none;
|
||||
}
|
30
chrome/content/zotero-platform/unix/itemPane.css
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Some distros have icons disabled by default at the OS level and
|
||||
* mozilla is a respectful gent.
|
||||
*/
|
||||
#zotero-feed-item-addTo-button .button-icon {
|
||||
display: block;
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
/* Set to hidden in user-agent css for some reason. */
|
||||
#zotero-feed-item-addTo-button .menu-iconic-left {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.zotero-item-pane-content {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* Make the item pane appear white (same colour as treeview), making the UI more consistent */
|
||||
.zotero-item-pane-content tab, .zotero-item-pane-content tabpanels {
|
||||
background-color: -moz-Field; /* Same as background colour for treeview */
|
||||
}
|
||||
|
||||
/* Possibly irrelevant if mozilla fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1306425 */
|
||||
.zotero-view-tabbox tabs tab[visuallyselected=true] {
|
||||
margin-top: 0px !important; /* Importanter than ./itemPane.css:20 */
|
||||
margin-bottom: -2px !important; /* Importanter than skin/itemPane.css:12 */
|
||||
}
|
||||
.zotero-view-tabbox tabs tab {
|
||||
margin-top: 2px !important; /* Importanter than skin/itemPane.css:11 */
|
||||
}
|
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
69
chrome/content/zotero-platform/unix/overlay.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
@media (min-resolution: 1.25dppx) {
|
||||
#zotero-pane-stack .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync > .toolbarbutton-icon {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dropmarker added automatically on Linux */
|
||||
.toolbarbutton-menu-dropmarker, #zotero-tb-search-menu-button {
|
||||
list-style-image: none;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
/* Fixes tabs missing styling on (GTK 3.20) Ubuntu 16.10. See https://bugzilla.mozilla.org/show_bug.cgi?id=1306425 */
|
||||
tabpanels {
|
||||
-moz-appearance: none;
|
||||
border: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||
|
||||
}
|
||||
tab {
|
||||
-moz-appearance: none;
|
||||
border-top: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||
border-right: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||
border-left: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||
}
|
||||
/* Fixes misc Ubuntu 16.10 rendering issue fixes. */
|
||||
#zotero-prefs menulist dropmarker{
|
||||
width: 30px;
|
||||
}
|
||||
#zotero-prefs .numberbox-input-box{
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
#zotero-pane splitter {
|
||||
border: 0;
|
||||
width: 6px;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#zotero-context-splitter-stacked {
|
||||
-moz-appearance: none;
|
||||
background-color: #ececec;
|
||||
border-top: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||
}
|
||||
|
||||
.zotero-tb-button:focus {
|
||||
border: 1px dotted #999;
|
||||
}
|
111
chrome/content/zotero-platform/unix/preferences.css
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
prefwindow,
|
||||
prefwindow:root /* override :root from above */ {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-unix.xml#prefwindow");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
prefpane {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-unix.xml#prefpane");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
prefwindow > .paneDeckContainer {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
prefpane > .content-box {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > .paneDeckContainer {
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > prefpane > .content-box {
|
||||
-moz-box-flex: 1;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
preferences {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-unix.xml#preferences");
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
preference {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-unix.xml#preference");
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
radio[pane] {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-unix.xml#panebutton") !important;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
prefwindow[chromehidden~="toolbar"] .chromeclass-toolbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
prefwindow {
|
||||
padding: 0px;
|
||||
|
||||
-moz-appearance: window;
|
||||
background-color: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
prefpane {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > prefpane {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.prefWindow-dlgbuttons {
|
||||
padding-bottom: 8px;
|
||||
padding-inline-start: 8px;
|
||||
padding-inline-end: 8px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] .prefWindow-dlgbuttons {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
radio[pane] {
|
||||
-moz-appearance: none;
|
||||
min-width: 4.5em;
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
.paneSelector {
|
||||
-moz-appearance: listbox;
|
||||
margin: 8px 8px 0 8px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.paneButtonIcon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
radio[pane][selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
#sync-reset-library-menu {
|
||||
height: initial !important;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/* There's an ugly horizontal scrollbar on linux in some steps of the wizard, which this fixes */
|
||||
.wizard-page-box {
|
||||
margin: 10px 40px;
|
||||
}
|
|
@ -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
|
||||
|
||||
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;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://zotero/locale/mozilla/browser.dtd"> %browserDTD;
|
||||
]>
|
||||
<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">
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<key id="key_quitApplication"
|
||||
key="&quitApplicationCmd.accesskey;"
|
||||
command="cmd_quitApplication"
|
||||
modifiers="accel"/>
|
||||
</keyset>
|
||||
|
||||
<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="&preferencesCmdUnix.label;"
|
||||
accesskey="&preferencesCmdUnix.accesskey;"
|
||||
oncommand="Zotero.Utilities.Internal.openPreferences();"/>
|
||||
</menupopup>
|
||||
</overlay>
|
0
chrome/content/zotero-platform/unix/tab.css
Normal file
3
chrome/content/zotero-platform/unix/tagselector.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
#view-settings-menu .toolbarbutton-icon {
|
||||
margin-right: 0; /* dropmarker spacing handled automatically on Linux */
|
||||
}
|
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 |
8
chrome/content/zotero-platform/unix/zotero.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
#zotero-feed-settings dropmarker{
|
||||
width: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#zotero-feed-settings .html-input {
|
||||
padding: 2px 2px 3px;
|
||||
}
|
0
chrome/content/zotero-platform/win/attachmentbox.css
Normal file
44
chrome/content/zotero-platform/win/integration.css
Normal file
|
@ -0,0 +1,44 @@
|
|||
window.citation-dialog {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.citation-dialog.search {
|
||||
background: white;
|
||||
padding: 2px 2px 2px 0;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border-radius: 10px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.citation-dialog.search:not([multiline="true"]) {
|
||||
height: 28px !important;
|
||||
}
|
||||
|
||||
.citation-dialog.entry {
|
||||
background: -moz-linear-gradient(-90deg, rgb(243,123,119) 0, rgb(180,47,38) 50%, rgb(156,36,27) 50%);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.note-dialog .citation-dialog.entry {
|
||||
background: -moz-linear-gradient(-90deg, rgb(249, 231, 179) 0, rgb(228, 193, 94) 50%, rgb(221, 184, 81) 50%);
|
||||
}
|
||||
|
||||
.citation-dialog.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;
|
||||
}
|
0
chrome/content/zotero-platform/win/itemPane.css
Normal file
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
165
chrome/content/zotero-platform/win/overlay.css
Normal file
|
@ -0,0 +1,165 @@
|
|||
:root {
|
||||
--theme-border-color: #cecece;
|
||||
}
|
||||
|
||||
/* Hide horrible blue effect for menu bar and toolbar */
|
||||
#navigator-toolbox {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
#zotero-pane #zotero-toolbar {
|
||||
-moz-appearance: none !important;
|
||||
margin-top: -3px;
|
||||
border: 1px solid var(--theme-border-color);
|
||||
}
|
||||
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
#zotero-pane-stack .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync > .toolbarbutton-icon {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button {
|
||||
margin: 0 -1px 0 -4px;
|
||||
padding: 5px 0 5px 5px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#zotero-tb-search-menu-button .button-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#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-view-tabbox tab {
|
||||
padding-left: .7em;
|
||||
padding-right: .7em;
|
||||
}
|
||||
|
||||
#zotero-toolbar {
|
||||
-moz-appearance: toolbox !important;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed]),
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
position: relative;
|
||||
/* Positive z-index positions the splitter on top of its siblings and makes
|
||||
it clickable on both sides. */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#zotero-context-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed]):not([orient=vertical]),
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter:not([state=collapsed]) {
|
||||
border-inline-end: 1px solid var(--theme-border-color);
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
margin-inline-start: -3px;
|
||||
}
|
||||
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed])[orient=vertical],
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) {
|
||||
border-block-end: 1px solid var(--theme-border-color);
|
||||
min-height: 0;
|
||||
height: 3px;
|
||||
margin-block-start: -3px;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter > grippy,
|
||||
#zotero-items-splitter > grippy,
|
||||
#zotero-tags-splitter > grippy,
|
||||
#zotero-context-splitter > grippy {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-items-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-tags-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-context-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) > grippy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
tree {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
#zotero-tag-selector groupbox {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#tags-box {
|
||||
padding-top: 0.1em;
|
||||
padding-left: 0.05em;
|
||||
}
|
||||
|
||||
#tags-box button {
|
||||
margin: .04em 0 0 .15em !important;
|
||||
}
|
||||
|
||||
.zotero-editpane-tabs spacer {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.zotero-view-item {
|
||||
padding: 0 !important;
|
||||
-moz-appearance: none;
|
||||
background-color: -moz-field;
|
||||
border-width: 1px 0 0 0;
|
||||
border-color: var(--theme-border-color);
|
||||
}
|
||||
|
||||
.zotero-editpane-tabs {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
#zotero-item-pane-groupbox {
|
||||
-moz-appearance: none !important;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
121
chrome/content/zotero-platform/win/preferences.css
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
prefwindow,
|
||||
prefwindow:root /* override :root from above */ {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-win.xml#prefwindow");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
prefpane {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-win.xml#prefpane");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
prefwindow > .paneDeckContainer {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
prefpane > .content-box {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > .paneDeckContainer {
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > prefpane > .content-box {
|
||||
-moz-box-flex: 1;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
preferences {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-win.xml#preferences");
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
preference {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-win.xml#preference");
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
radio[pane] {
|
||||
-moz-binding: url("chrome://zotero/content/bindings/preferences-win.xml#panebutton") !important;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
prefwindow[chromehidden~="toolbar"] .chromeclass-toolbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
prefwindow {
|
||||
padding: 0px;
|
||||
|
||||
-moz-appearance: window;
|
||||
background-color: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
prefpane {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 10px;
|
||||
padding-inline-start: 8px;
|
||||
padding-inline-end: 10px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 10px;
|
||||
padding-inline-start: 8px;
|
||||
padding-inline-end: 10px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] > prefpane {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.prefWindow-dlgbuttons {
|
||||
padding-bottom: 10px;
|
||||
padding-inline-start: 8px;
|
||||
padding-inline-end: 10px;
|
||||
}
|
||||
|
||||
prefwindow[type="child"] .prefWindow-dlgbuttons {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
radio[pane] {
|
||||
-moz-appearance: none;
|
||||
margin: 0px 1px 0px 1px;
|
||||
padding: 1px 3px 1px 3px;
|
||||
min-width: 4.5em;
|
||||
}
|
||||
|
||||
.paneSelector {
|
||||
border-bottom: 2px groove ThreeDFace;
|
||||
margin: 0px;
|
||||
padding-inline-start: 10px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
.paneButtonIcon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
radio[pane]:hover {
|
||||
background-color: #E0E8F6;
|
||||
color: black;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
radio[pane][selected="true"] {
|
||||
background-color: #C1D2EE;
|
||||
color: black;
|
||||
-moz-appearance: none;
|
||||
}
|
|
@ -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;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://zotero/locale/mozilla/browser.dtd"> %browserDTD;
|
||||
]>
|
||||
<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;"
|
||||
accesskey="&quitApplicationCmdWin.accesskey;"
|
||||
command="cmd_quitApplication"/>
|
||||
</menupopup>
|
||||
<menupopup id="menu_EditPopup">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_preferences"
|
||||
label="&preferencesCmdUnix.label;"
|
||||
accesskey="&preferencesCmdUnix.accesskey;"
|
||||
oncommand="Zotero.Utilities.Internal.openPreferences();"/>
|
||||
</menupopup>
|
||||
</overlay>
|
0
chrome/content/zotero-platform/win/tab.css
Normal file
3
chrome/content/zotero-platform/win/tagselector.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
button {
|
||||
font-family: Segoe UI, sans-serif;
|
||||
}
|
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 |
86
chrome/content/zotero/about.xul
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?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"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/zotero-react-client.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">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||
<img id="logo" src="chrome://zotero/skin/zotero.svg" alt="Zotero" />
|
||||
</div>
|
||||
<hbox>
|
||||
<label id="version"/>
|
||||
<label id="changelog" class="zotero-text-link" value="&zotero.whatsNew;"/>
|
||||
</hbox>
|
||||
<script>
|
||||
document.getElementById('version').textContent = Zotero.version;
|
||||
</script>
|
||||
<vbox>
|
||||
<div id="about-text" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="created-by"></p>
|
||||
<p id="third-party-software"></p>
|
||||
<p id="get-involved"></p>
|
||||
<script><![CDATA[
|
||||
Components.utils.import("resource://zotero/config.js");
|
||||
|
||||
document.getElementById('changelog').href = ZOTERO_CONFIG.CHANGELOG_URL;
|
||||
|
||||
// Replace [links] in localized strings with spans with onclick handlers
|
||||
//
|
||||
// TODO: Use helper function in common with intro text in itemTreeView.js
|
||||
document.getElementById('created-by').innerHTML =
|
||||
Zotero.Utilities.htmlSpecialChars(
|
||||
Zotero.getString(
|
||||
'about.createdBy',
|
||||
[Zotero.appName, `[${ZOTERO_CONFIG.PRODUCER}]`]
|
||||
),
|
||||
)
|
||||
.replace(
|
||||
/\[([^\]]+)](.+)\[([^\]]+)]/,
|
||||
`<span data-href="${ZOTERO_CONFIG.PRODUCER_URL}">$1</span>`
|
||||
+ '$2'
|
||||
+ `<span data-href="${ZOTERO_CONFIG.CREDITS_URL}">$3</span>`
|
||||
);
|
||||
|
||||
document.getElementById('third-party-software').innerHTML =
|
||||
Zotero.Utilities.htmlSpecialChars(
|
||||
Zotero.getString('about.openSource', Zotero.appName)
|
||||
)
|
||||
.replace(
|
||||
/\[([^\]]+)](.+)\[([^\]]+)]/,
|
||||
`<span data-href="${ZOTERO_CONFIG.LICENSING_URL}">$1</span>`
|
||||
+ '$2'
|
||||
+ `<span data-href="${ZOTERO_CONFIG.CREDITS_URL}#third-party_software">$3</span>`
|
||||
);
|
||||
|
||||
document.getElementById('get-involved').innerHTML =
|
||||
Zotero.Utilities.htmlSpecialChars(Zotero.getString('about.getInvolved'))
|
||||
.replace(
|
||||
/\[([^\]]+)]/,
|
||||
`<span data-href="${ZOTERO_CONFIG.GET_INVOLVED_URL}">$1</span>`
|
||||
);
|
||||
|
||||
// Activate text links
|
||||
for (let span of document.getElementById('about-text').getElementsByTagName('span')) {
|
||||
span.className = 'text-link';
|
||||
span.onclick = function () {
|
||||
Zotero.launchURL(this.getAttribute('data-href'));
|
||||
};
|
||||
}
|
||||
]]></script>
|
||||
</div>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</dialog>
|
12
chrome/content/zotero/ace/ace.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script type="text/javascript" src="chrome://zotero/content/include.js"></script>
|
||||
<script type="text/javascript" src="resource://zotero/ace/ace.js"></script>
|
||||
<!-- Enable for autocomplete -->
|
||||
<!--<script type="text/javascript" src="resource://zotero/ace/ext-language_tools.js"></script>-->
|
||||
<script type="text/javascript" src="resource://zotero/ace/mode-javascript.js"></script>
|
||||
<script type="text/javascript" src="aceWrapper.js"></script>
|
||||
</head>
|
||||
<body id="body"></body>
|
||||
</html>
|
41
chrome/content/zotero/ace/aceWrapper.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
***** 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 editor, JavaScriptMode, TextMode, EditSession;
|
||||
window.addEventListener("DOMContentLoaded", function(e) {
|
||||
var div = document.createElement("div");
|
||||
div.style.position = "absolute";
|
||||
div.style.top = "0px";
|
||||
div.style.left = "0px";
|
||||
div.style.right = "0px";
|
||||
div.style.bottom = "0px";
|
||||
div.id = "ace-div";
|
||||
document.getElementById("body").appendChild(div);
|
||||
|
||||
JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
TextMode = require("ace/mode/text").Mode;
|
||||
EditSession = require("ace/edit_session").EditSession;
|
||||
editor = ace.edit('ace-div');
|
||||
}, false);
|
190
chrome/content/zotero/advancedSearch.js
Normal file
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
***** 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/Services.jsm");
|
||||
import ItemTree from 'zotero/itemTree';
|
||||
import { getDefaultColumnsByDataKeys } from 'zotero/itemTreeColumns';
|
||||
|
||||
|
||||
var ZoteroAdvancedSearch = new function() {
|
||||
this.onLoad = onLoad;
|
||||
this.search = search;
|
||||
this.clear = clear;
|
||||
this.onItemActivate = onItemActivate;
|
||||
|
||||
this.itemsView = false;
|
||||
|
||||
var _searchBox;
|
||||
var _libraryID;
|
||||
|
||||
async 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];
|
||||
|
||||
io.dataIn.search.loadPrimaryData()
|
||||
.then(function () {
|
||||
_searchBox.search = io.dataIn.search;
|
||||
});
|
||||
|
||||
var elem = document.getElementById('zotero-items-tree');
|
||||
this.itemsView = await ItemTree.init(elem, {
|
||||
id: "advanced-search",
|
||||
dragAndDrop: true,
|
||||
onActivate: this.onItemActivate.bind(this),
|
||||
columns: getDefaultColumnsByDataKeys(['title', 'firstCreator']),
|
||||
});
|
||||
|
||||
// A minimal implementation of Zotero.CollectionTreeRow
|
||||
var collectionTreeRow = {
|
||||
view: {},
|
||||
ref: _searchBox.search,
|
||||
isSearchMode: () => true,
|
||||
getItems: async () => [],
|
||||
isLibrary: () => false,
|
||||
isCollection: () => false,
|
||||
isSearch: () => true,
|
||||
isPublications: () => false,
|
||||
isDuplicates: () => false,
|
||||
isFeed: () => false,
|
||||
isShare: () => false,
|
||||
isTrash: () => false
|
||||
};
|
||||
|
||||
this.itemsView.changeCollectionTreeRow(collectionTreeRow);
|
||||
}
|
||||
|
||||
this.onUnload = function () {
|
||||
this.itemsView.unregister();
|
||||
}
|
||||
|
||||
function search() {
|
||||
_searchBox.updateSearch();
|
||||
_searchBox.active = true;
|
||||
|
||||
// A minimal implementation of Zotero.CollectionTreeRow
|
||||
var collectionTreeRow = {
|
||||
view: {},
|
||||
ref: _searchBox.search,
|
||||
isSearchMode: () => true,
|
||||
getItems: async function () {
|
||||
await Zotero.Libraries.get(_libraryID).waitForDataLoad('item');
|
||||
|
||||
var search = _searchBox.search.clone();
|
||||
search.libraryID = _libraryID;
|
||||
var ids = await search.search();
|
||||
return Zotero.Items.get(ids);
|
||||
},
|
||||
isLibrary: () => false,
|
||||
isCollection: () => false,
|
||||
isSearch: () => true,
|
||||
isPublications: () => false,
|
||||
isDuplicates: () => false,
|
||||
isFeed: () => false,
|
||||
isShare: () => false,
|
||||
isTrash: () => false
|
||||
};
|
||||
|
||||
this.itemsView.changeCollectionTreeRow(collectionTreeRow);
|
||||
}
|
||||
|
||||
|
||||
function clear() {
|
||||
this.itemsView.changeCollectionTreeRow(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;
|
||||
}
|
||||
|
||||
|
||||
this.save = Zotero.Promise.coroutine(function* () {
|
||||
_searchBox.updateSearch();
|
||||
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
||||
var libraryID = _searchBox.search.libraryID;
|
||||
|
||||
var searches = yield Zotero.Searches.getAll(libraryID)
|
||||
var prefix = Zotero.getString('pane.collections.untitled');
|
||||
var name = Zotero.Utilities.Internal.getNextName(
|
||||
prefix,
|
||||
searches.map(s => s.name).filter(n => n.startsWith(prefix))
|
||||
);
|
||||
|
||||
name = { value: name };
|
||||
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;
|
||||
yield s.saveTx();
|
||||
|
||||
window.close();
|
||||
});
|
||||
|
||||
|
||||
this.onLibraryChange = function (libraryID) {
|
||||
_libraryID = libraryID;
|
||||
var library = Zotero.Libraries.get(libraryID);
|
||||
var isEditable = library.editable && library.libraryType != 'publications';
|
||||
document.getElementById('zotero-search-save').disabled = !isEditable;
|
||||
}
|
||||
|
||||
|
||||
function onItemActivate(event, items)
|
||||
{
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
|
||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||
|
||||
if (!lastWin) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastWin.ZoteroPane.selectItems(items.map(item => item.id), false);
|
||||
lastWin.focus();
|
||||
}
|
||||
}
|
47
chrome/content/zotero/advancedSearch.xul
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?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"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/zotero-react-client.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"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
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>
|
||||
<hbox class="virtualized-table-container" flex="1">
|
||||
<html:div id="zotero-items-tree"/>
|
||||
</hbox>
|
||||
</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>
|
329
chrome/content/zotero/bibliography.js
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
***** 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
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
var Zotero_File_Interface_Bibliography = new function() {
|
||||
var _io;
|
||||
|
||||
// Only changes when explicitly selected
|
||||
var lastSelectedStyle,
|
||||
lastSelectedLocale;
|
||||
|
||||
var isDocPrefs = false;
|
||||
var isRTFScan = false;
|
||||
|
||||
/**
|
||||
* Initialize some variables and prepare event listeners for when chrome is done
|
||||
* loading
|
||||
*
|
||||
* @param {Object} [args] - Explicit arguments in place of window arguments
|
||||
*/
|
||||
this.init = Zotero.Promise.coroutine(function* (args = {}) {
|
||||
// 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 if (args) {
|
||||
_io = args;
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
// See note in style.js
|
||||
if (!Zotero.Styles.initialized) {
|
||||
// Initialize styles
|
||||
yield Zotero.Styles.init();
|
||||
}
|
||||
|
||||
// add styles to list
|
||||
|
||||
var styles = Zotero.Styles.getVisible();
|
||||
var selectIndex = null;
|
||||
for (let i=0; i < styles.length; i++) {
|
||||
var itemNode = document.createElement("listitem");
|
||||
itemNode.setAttribute("value", styles[i].styleID);
|
||||
let title = styles[i].title;
|
||||
// Add acronyms to APA and ASA to avoid confusion
|
||||
// https://forums.zotero.org/discussion/comment/357135/#Comment_357135
|
||||
title = title
|
||||
.replace(/^American Psychological Association/, "American Psychological Association (APA)")
|
||||
.replace(/^American Sociological Association/, "American Sociological Association (ASA)");
|
||||
itemNode.setAttribute("label", title);
|
||||
listbox.appendChild(itemNode);
|
||||
|
||||
if(styles[i].styleID == _io.style) {
|
||||
selectIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (listbox.selectedIndex == -1) {
|
||||
// This can happen in tests if styles aren't loaded
|
||||
Zotero.debug("No styles to select", 2);
|
||||
return;
|
||||
}
|
||||
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: set selected endnotes/footnotes
|
||||
isDocPrefs = !!document.getElementById("displayAs");
|
||||
isRTFScan = !document.getElementById("formatUsing");
|
||||
if (isDocPrefs && !isRTFScan) {
|
||||
if(_io.useEndnotes && _io.useEndnotes == 1) document.getElementById("displayAs").selectedIndex = 1;
|
||||
|
||||
let dialog = document.getElementById("zotero-doc-prefs-dialog");
|
||||
dialog.setAttribute('title', `${Zotero.clientName} - ${dialog.getAttribute('title')}`);
|
||||
|
||||
if (document.getElementById("formatUsing-groupbox")) {
|
||||
if (["Field", "ReferenceMark"].includes(_io.primaryFieldType)) {
|
||||
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");
|
||||
} else {
|
||||
document.getElementById("formatUsing-groupbox").style.display = "none";
|
||||
_io.fieldType = _io.primaryFieldType;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
document.getElementById("automaticCitationUpdates-checkbox").checked = !_io.delayCitationUpdates;
|
||||
}
|
||||
|
||||
if (_io.showImportExport) {
|
||||
document.querySelector('#exportImport').hidden = false;
|
||||
}
|
||||
}
|
||||
|
||||
// set style to false, in case this is cancelled
|
||||
_io.style = false;
|
||||
});
|
||||
|
||||
this.openHelpLink = function() {
|
||||
Zotero.launchURL("https://www.zotero.org/support/word_processor_integration");
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 and rtfScan.xul
|
||||
//
|
||||
if (isDocPrefs) {
|
||||
// update status of displayAs box based on style class
|
||||
var isNote = selectedStyleObj.class == "note";
|
||||
var multipleNotesSupported = _io.supportedNotes.length > 1;
|
||||
document.getElementById("displayAs-groupbox").hidden = !isNote || !multipleNotesSupported;
|
||||
|
||||
// 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();
|
||||
};
|
||||
|
||||
this.exportDocument = function () {
|
||||
if (Zotero.Integration.confirmExportDocument()) {
|
||||
_io.exportDocument = true;
|
||||
document.documentElement.acceptDialog();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(isDocPrefs) {
|
||||
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.delayCitationUpdates = !document.getElementById("automaticCitationUpdates-checkbox").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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.manageStyles = function () {
|
||||
document.documentElement.getButton('cancel').click();
|
||||
var win = Zotero.Utilities.Internal.openPreferences('zotero-prefpane-cite', { tab: 'styles-tab' });
|
||||
if (isDocPrefs) {
|
||||
Zotero.Utilities.Internal.activate(win);
|
||||
}
|
||||
};
|
||||
}
|
46
chrome/content/zotero/bibliography.xul
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?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()"/>
|
||||
<hbox align="right">
|
||||
<label id="manage-styles" class="text-link"
|
||||
onclick="Zotero_File_Interface_Bibliography.manageStyles()">&zotero.bibliography.manageStyles;</label>
|
||||
</hbox>
|
||||
</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>
|
642
chrome/content/zotero/bindings/attachmentbox.xml
Normal file
|
@ -0,0 +1,642 @@
|
|||
<?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.synchronous = 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.synchronous = true;
|
||||
this.displayURL = true;
|
||||
this.displayFileName = true;
|
||||
this.displayAccessed = true;
|
||||
this.displayNote = true;
|
||||
this.displayDateModified = true;
|
||||
break;
|
||||
|
||||
case 'mergeedit':
|
||||
this.synchronous = true;
|
||||
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;
|
||||
|
||||
case 'filemerge':
|
||||
this.synchronous = true;
|
||||
this.displayURL = true;
|
||||
this.displayFileName = true;
|
||||
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;">
|
||||
<setter><![CDATA[
|
||||
if (!(val instanceof Zotero.Item)) {
|
||||
throw new Error("'item' must be a Zotero.Item");
|
||||
}
|
||||
this._item = val;
|
||||
this.refresh();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<!-- Methods -->
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'attachmentbox');
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Zotero.Notifier.unregisterObserver(this._notifierID);
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
<method name="notify">
|
||||
<parameter name="event"/>
|
||||
<parameter name="type"/>
|
||||
<parameter name="ids"/>
|
||||
<parameter name="extraData"/>
|
||||
<body><![CDATA[
|
||||
if (event != 'modify' || !this.item || !this.item.id) return;
|
||||
for (let id of ids) {
|
||||
if (id != this.item.id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var noteEditor = this._id('attachment-note-editor')
|
||||
if (extraData
|
||||
&& extraData[id]
|
||||
&& extraData[id].noteEditorID
|
||||
&& extraData[id].noteEditorID == noteEditor.instanceID) {
|
||||
//Zotero.debug("Skipping notification from current attachment note field");
|
||||
continue;
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
break;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<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, and use value attribute for empty field
|
||||
if ((firstSpace == -1 && val.length > 29 ) || firstSpace > 29 || val === "") {
|
||||
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('tooltiptext', urlSpec);
|
||||
urlField.setAttribute('hidden', false);
|
||||
if (this.clickableLink) {
|
||||
urlField.onclick = function (event) {
|
||||
if (event.button != 2) {
|
||||
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');
|
||||
let val = this.item.getField('accessDate');
|
||||
if (val) {
|
||||
val = Zotero.Date.sqlToDate(val, true);
|
||||
}
|
||||
if (val) {
|
||||
this._id("accessed").value = val.toLocaleString();
|
||||
accessed.hidden = false;
|
||||
}
|
||||
else {
|
||||
accessed.hidden = true;
|
||||
}
|
||||
}
|
||||
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.attachmentFilename;
|
||||
|
||||
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) {
|
||||
Zotero.Fulltext.getPages(this.item.id)
|
||||
.then(function (pages) {
|
||||
if (!this.item) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
else {
|
||||
pagesRow.hidden = true;
|
||||
}
|
||||
|
||||
if (this.displayDateModified) {
|
||||
this._id("dateModified-label").value = Zotero.getString('itemFields.dateModified')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
// Conflict resolution uses a modal window, so promises won't work, but
|
||||
// the sync process passes in the file mod time as dateModified
|
||||
if (this.synchronous) {
|
||||
this._id("dateModified").value = Zotero.Date.sqlToDate(
|
||||
this.item.getField('dateModified'), true
|
||||
).toLocaleString();
|
||||
dateModifiedRow.hidden = false;
|
||||
}
|
||||
else {
|
||||
this.item.attachmentModificationTime
|
||||
.then(function (mtime) {
|
||||
if (!this._id) return;
|
||||
|
||||
if (mtime) {
|
||||
this._id("dateModified").value = new Date(mtime).toLocaleString();
|
||||
}
|
||||
dateModifiedRow.hidden = !mtime;
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
else {
|
||||
dateModifiedRow.hidden = true;
|
||||
}
|
||||
|
||||
// Full-text index information
|
||||
if (this.displayIndexed) {
|
||||
this.updateItemIndexedState()
|
||||
.then(function () {
|
||||
if (!this.item) return;
|
||||
indexStatusRow.hidden = false;
|
||||
}.bind(this));
|
||||
}
|
||||
else {
|
||||
indexStatusRow.hidden = true;
|
||||
}
|
||||
|
||||
var type = Zotero.Libraries.get(this.item.libraryID).libraryType;
|
||||
var noteEditor = this._id('attachment-note-editor');
|
||||
|
||||
if (this.displayNote && (this.displayNoteIfEmpty || this.item.note != '')) {
|
||||
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;
|
||||
}
|
||||
noteEditor.viewMode = 'library';
|
||||
|
||||
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[
|
||||
return Zotero.spawn(function* () {
|
||||
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 = yield 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 = yield 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.text1')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (newTitle.value != oldTitle) {
|
||||
item.setField('title', newTitle.value);
|
||||
yield item.saveTx();
|
||||
}
|
||||
}.bind(this));
|
||||
]]>
|
||||
</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[
|
||||
return Zotero.spawn(function* () {
|
||||
var indexStatus = this._id('index-status');
|
||||
var reindexButton = this._id('reindex');
|
||||
|
||||
var status = yield Zotero.Fulltext.getIndexedState(this.item);
|
||||
if (!this.item) return;
|
||||
|
||||
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_QUEUED:
|
||||
str += 'queued';
|
||||
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);
|
||||
|
||||
var show = false;
|
||||
if (this.editable) {
|
||||
show = yield Zotero.Fulltext.canReindex(this.item);
|
||||
if (!this.item) return;
|
||||
}
|
||||
|
||||
if (show) {
|
||||
reindexButton.setAttribute('hidden', false);
|
||||
}
|
||||
else {
|
||||
reindexButton.setAttribute('hidden', true);
|
||||
}
|
||||
}, this);
|
||||
]]></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">
|
||||
<vbox id="metadata">
|
||||
<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" hidden="true">
|
||||
<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>
|
||||
</vbox>
|
||||
|
||||
<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>
|
183
chrome/content/zotero/bindings/filesyncstatus.xml
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?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 (let libraryID of newLibraries) {
|
||||
libraryNames.push({
|
||||
libraryID: libraryID,
|
||||
name: Zotero.Libraries.getName(libraryID)
|
||||
});
|
||||
}
|
||||
var collation = Zotero.getLocaleCollation();
|
||||
let userLibraryID = Zotero.Libraries.userLibraryID;
|
||||
libraryNames.sort(function (a, b) {
|
||||
if (a.libraryID == userLibraryID) {
|
||||
return -1;
|
||||
}
|
||||
if (b.libraryID == userLibraryID) {
|
||||
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>
|
2788
chrome/content/zotero/bindings/itembox.xml
Normal file
452
chrome/content/zotero/bindings/merge.xml
Normal file
|
@ -0,0 +1,452 @@
|
|||
<?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"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<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="libraryID"/>
|
||||
|
||||
<field name="_data"/>
|
||||
<property name="data" onget="return this._data;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._data = val;
|
||||
this.refresh();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="merged" onget="return this._mergepane.data"/>
|
||||
|
||||
<field name="_type"/>
|
||||
<property name="type" onget="return this._type;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
switch (val) {
|
||||
case 'item':
|
||||
case 'attachment':
|
||||
case 'note':
|
||||
case 'annotation':
|
||||
case 'file':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported merge object type '${type}'`);
|
||||
}
|
||||
|
||||
this._type = val;
|
||||
var hbox = document.getAnonymousNodes(this)[0];
|
||||
hbox.setAttribute('mergetype', 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"/>
|
||||
|
||||
<field name="_leftpane"/>
|
||||
<property name="leftpane" onget="return this._leftpane"/>
|
||||
<field name="_rightpane"/>
|
||||
<property name="rightpane" onget="return this._rightpane"/>
|
||||
<field name="_mergepane"/>
|
||||
<property name="mergepane" onget="return this._mergepane"/>
|
||||
|
||||
<property name="onSelectionChange"/>
|
||||
|
||||
<method name="refresh">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._data.left.deleted && this._data.right.deleted) {
|
||||
throw new Error("'left' and 'right' cannot both be deleted");
|
||||
}
|
||||
|
||||
// Check for note or attachment
|
||||
this.type = this._getTypeFromObject(
|
||||
this._data.left.deleted ? this._data.right : this._data.left
|
||||
);
|
||||
|
||||
var showButton = this.type != 'item';
|
||||
|
||||
this._leftpane.showButton = showButton;
|
||||
this._rightpane.showButton = showButton;
|
||||
this._leftpane.libraryID = this.libraryID;
|
||||
this._rightpane.libraryID = this.libraryID;
|
||||
this._mergepane.libraryID = this.libraryID;
|
||||
this._leftpane.data = this._data.left;
|
||||
this._rightpane.data = this._data.right;
|
||||
this._mergepane.data = this._data.merge;
|
||||
|
||||
if (this._data.selected == 'left') {
|
||||
this.choosePane(this._leftpane);
|
||||
}
|
||||
else {
|
||||
this.choosePane(this._rightpane);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
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="choosePane">
|
||||
<parameter name="pane"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (pane.getAttribute('anonid') == 'leftpane') {
|
||||
var position = 'left';
|
||||
var otherPane = this._rightpane;
|
||||
}
|
||||
else {
|
||||
var position = 'right';
|
||||
var otherPane = this._leftpane;
|
||||
}
|
||||
|
||||
pane.removeAttribute("selected");
|
||||
otherPane.removeAttribute("selected");
|
||||
pane.setAttribute("selected", "true");
|
||||
|
||||
if (pane.deleted) {
|
||||
this._mergepane.deleted = true;
|
||||
}
|
||||
else {
|
||||
this._mergepane.data = pane.data;
|
||||
}
|
||||
|
||||
if (this.onSelectionChange) {
|
||||
this.onSelectionChange();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="_getTypeFromObject">
|
||||
<parameter name="obj"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!obj.itemType) {
|
||||
Zotero.debug(obj, 1);
|
||||
throw new Error("obj is not item JSON");
|
||||
}
|
||||
switch (obj.itemType) {
|
||||
case 'attachment':
|
||||
case 'note':
|
||||
case 'annotation':
|
||||
return obj.itemType;
|
||||
}
|
||||
return 'item';
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('anonid',id)[0];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:hbox id="merge-group" flex="1">
|
||||
<xul:zoteromergepane anonid="leftpane" flex="1"/>
|
||||
<xul:zoteromergepane anonid="rightpane" flex="1"/>
|
||||
<xul:zoteromergepane anonid="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);
|
||||
this.isMergePane = this.getAttribute('anonid') == 'mergepane';
|
||||
|
||||
if (!this.isMergePane) {
|
||||
this.pane.onclick = function () {
|
||||
this.parent.choosePane(this);
|
||||
}.bind(this);
|
||||
}
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="type" onget="return this.parent.type" readonly="true"/>
|
||||
<property name="caption" onget="return this._id('caption')" readonly="true"/>
|
||||
<field name="showButton"/>
|
||||
<property name="pane" onget="return document.getAnonymousNodes(this)[0]"/>
|
||||
<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>
|
||||
|
||||
<field name="libraryID"/>
|
||||
|
||||
<field name="_data"/>
|
||||
<property name="data" onget="return this._data">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._data = val;
|
||||
|
||||
var button = this._id('choose-button');
|
||||
button.label = Zotero.getString('sync.conflict.chooseThisVersion');
|
||||
if (this.showButton) {
|
||||
button.onclick = () => this.parent.choosePane(this);
|
||||
button.style.visibility = 'visible';
|
||||
}
|
||||
else {
|
||||
button.style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
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':
|
||||
case 'file':
|
||||
elementName = 'zoteroattachmentbox';
|
||||
break;
|
||||
|
||||
case 'note':
|
||||
var type = Zotero.Libraries.get(this.libraryID).libraryType;
|
||||
elementName = 'zoteronoteeditor';
|
||||
break;
|
||||
|
||||
case 'annotation':
|
||||
elementName = 'div';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Object type '" + this.type + "' not supported");
|
||||
}
|
||||
|
||||
if (elementName == 'div') {
|
||||
let HTML_NS = 'http://www.w3.org/1999/xhtml';
|
||||
var objbox = document.createElementNS(HTML_NS, elementName);
|
||||
}
|
||||
else {
|
||||
var objbox = document.createElement(elementName);
|
||||
}
|
||||
|
||||
var parentRow = this._id('parent-row');
|
||||
if (val.parentItem) {
|
||||
parentRow.textContent = '';
|
||||
|
||||
let label = document.createElement('span');
|
||||
label.textContent = Zotero.getString('pane.item.parentItem');
|
||||
parentRow.appendChild(label);
|
||||
|
||||
let parentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, val.parentItem);
|
||||
let text = document.createTextNode(" " + parentItem.getDisplayTitle(true));
|
||||
parentRow.appendChild(text);
|
||||
|
||||
parentRow.hidden = false;
|
||||
}
|
||||
else {
|
||||
parentRow.hidden = true;
|
||||
}
|
||||
|
||||
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("anonid", "objectbox");
|
||||
objbox.setAttribute("flex", "1");
|
||||
objbox.mode = this.type == 'file' ? 'filemerge' : 'merge';
|
||||
|
||||
// Store JSON
|
||||
this._data = val;
|
||||
|
||||
// Create a copy of the JSON that we can clean for display, since the remote object
|
||||
// might reference things that don't exist locally
|
||||
var displayJSON = Object.assign({}, val);
|
||||
displayJSON.collections = [];
|
||||
|
||||
// Create item from JSON for metadata box
|
||||
var item = new Zotero.Item(val.itemType);
|
||||
item.libraryID = this.libraryID;
|
||||
item.fromJSON(displayJSON);
|
||||
|
||||
if (item.isAnnotation()) {
|
||||
Zotero.Annotations.toJSON(item)
|
||||
.then((data) => {
|
||||
Zotero.AnnotationBox.render(objbox, { data });
|
||||
});
|
||||
}
|
||||
else {
|
||||
objbox.item = item;
|
||||
}
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="parent"/>
|
||||
|
||||
<method name="click">
|
||||
<body><![CDATA[
|
||||
this.pane.click();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_id">
|
||||
<parameter name="id"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var elems = document.getAnonymousNodes(this)[0].getElementsByAttribute('anonid', id);
|
||||
return elems.length ? elems[0] : false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:vbox flex="1">
|
||||
<xul:groupbox anonid="merge-pane" flex="1">
|
||||
<xul:caption anonid="caption"/>
|
||||
<html:div anonid="parent-row" hidden="true"/>
|
||||
<xul:box anonid="object-placeholder"/>
|
||||
<xul:hbox anonid="delete-box" hidden="true" flex="1">
|
||||
<xul:label value="&zotero.merge.deleted;"/>
|
||||
</xul:hbox>
|
||||
</xul:groupbox>
|
||||
<xul:button anonid="choose-button"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
604
chrome/content/zotero/bindings/noteeditor.xml
Normal file
|
@ -0,0 +1,604 @@
|
|||
<?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="displayTags">false</field>
|
||||
<field name="displayRelated">false</field>
|
||||
<field name="displayButton">false</field>
|
||||
<field name="hideLinksContainer"/>
|
||||
|
||||
<field name="buttonCaption"/>
|
||||
<field name="parentClickHandler"/>
|
||||
<field name="keyDownHandler"/>
|
||||
<field name="commandHandler"/>
|
||||
<field name="clickHandler"/>
|
||||
<field name="navigateHandler"/>
|
||||
|
||||
<field name="returnHandler"/>
|
||||
|
||||
<constructor><![CDATA[
|
||||
this._destroyed = false;
|
||||
this._noteEditorID = Zotero.Utilities.randomString();
|
||||
this._iframe = document.getAnonymousElementByAttribute(this, 'anonid', 'editor-view');
|
||||
this._iframe.addEventListener('DOMContentLoaded', (e) => {
|
||||
// For iframes without chrome priviledges, for unknown reasons,
|
||||
// dataTransfer.getData() returns empty value for `drop` event
|
||||
// when dragging something from the outside of Zotero
|
||||
this._iframe.contentWindow.addEventListener('drop', (event) => {
|
||||
this._iframe.contentWindow.wrappedJSObject.droppedData = Components.utils.cloneInto({
|
||||
'text/plain': event.dataTransfer.getData('text/plain'),
|
||||
'text/html': event.dataTransfer.getData('text/html'),
|
||||
'zotero/annotation': event.dataTransfer.getData('zotero/annotation'),
|
||||
'zotero/item': event.dataTransfer.getData('zotero/item')
|
||||
}, this._iframe.contentWindow);
|
||||
}, true);
|
||||
this._initialized = true;
|
||||
});
|
||||
|
||||
window.fillTooltip = (tooltip) => {
|
||||
let node = window.document.tooltipNode.closest('*[title]');
|
||||
if (!node || !node.getAttribute('title')) {
|
||||
return false;
|
||||
}
|
||||
tooltip.setAttribute('label', node.getAttribute('title'));
|
||||
return true;
|
||||
}
|
||||
|
||||
this.saveSync = () => {
|
||||
if (this._editorInstance) {
|
||||
this._editorInstance.saveSync();
|
||||
}
|
||||
}
|
||||
|
||||
this.getCurrentInstance = () => {
|
||||
return this._editorInstance;
|
||||
}
|
||||
|
||||
this.initEditor = async (state, reloaded) => {
|
||||
if (this._editorInstance) {
|
||||
this._editorInstance.uninit();
|
||||
}
|
||||
|
||||
// Automatically upgrade editable v1 note before it's loaded
|
||||
// TODO: Remove this at some point
|
||||
if (this.editable) {
|
||||
await Zotero.Notes.upgradeSchemaV1(this._item);
|
||||
}
|
||||
|
||||
this._editorInstance = new Zotero.EditorInstance();
|
||||
await this._editorInstance.init({
|
||||
state,
|
||||
item: this._item,
|
||||
reloaded,
|
||||
iframeWindow: document.getAnonymousElementByAttribute(this, 'anonid', 'editor-view').contentWindow,
|
||||
popup: document.getAnonymousElementByAttribute(this, 'anonid', 'editor-menu'),
|
||||
onNavigate: this._navigateHandler,
|
||||
viewMode: this.viewMode,
|
||||
readOnly: !this.editable,
|
||||
disableUI: this.mode == 'merge',
|
||||
onReturn: this._returnHandler,
|
||||
placeholder: this.placeholder
|
||||
});
|
||||
if (this._onInitCallback) {
|
||||
this._onInitCallback();
|
||||
}
|
||||
}
|
||||
|
||||
this.onInit = (callback) => {
|
||||
if (this._editorInstance) {
|
||||
return callback();
|
||||
}
|
||||
this._onInitCallback = callback;
|
||||
}
|
||||
|
||||
this.notify = async (event, type, ids, extraData) => {
|
||||
if (this._editorInstance) {
|
||||
await this._editorInstance.notify(event, type, ids, extraData);
|
||||
}
|
||||
|
||||
if (!this.item) return;
|
||||
// Try to use the state from the item save event
|
||||
let id = this.item.id;
|
||||
if (ids.includes(id)) {
|
||||
if (event == 'delete') {
|
||||
if (this._returnHandler) {
|
||||
this._returnHandler();
|
||||
}
|
||||
}
|
||||
else {
|
||||
let state = extraData && extraData[id] && extraData[id].state;
|
||||
if (state) {
|
||||
if (extraData[id].noteEditorID !== this._editorInstance.instanceID) {
|
||||
this.initEditor(state, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let curValue = this.item.note;
|
||||
if (curValue !== this._lastHtmlValue) {
|
||||
this.initEditor(null, true);
|
||||
}
|
||||
}
|
||||
this._lastHtmlValue = this.item.note;
|
||||
}
|
||||
}
|
||||
|
||||
this._id('links-container').hidden = !(this.displayTags && this.displayRelated) || this._hideLinksContainer;
|
||||
this._id('links-box').refresh();
|
||||
}
|
||||
|
||||
this._notifierID = Zotero.Notifier.registerObserver(this, ['item', 'file'], 'noteeditor');
|
||||
]]></constructor>
|
||||
|
||||
<property name="editorInstance" onget="return this._editorInstance"/>
|
||||
|
||||
<!-- 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.displayTags = false;
|
||||
this.displayRelated = false;
|
||||
this.displayButton = false;
|
||||
|
||||
switch (val) {
|
||||
case 'view':
|
||||
case 'merge':
|
||||
this.editable = false;
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
this.editable = true;
|
||||
this.parentClickHandler = this.selectParent;
|
||||
this.keyDownHandler = this.handleKeyDown;
|
||||
this.commandHandler = this.save;
|
||||
this.displayTags = true;
|
||||
this.displayRelated = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in noteeditor.xml");
|
||||
}
|
||||
|
||||
this._mode = val;
|
||||
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
||||
this._id('links-box').mode = val;
|
||||
this._id('links-container').hidden = !(this.displayTags && this.displayRelated) || this._hideLinksContainer;
|
||||
this._id('links-box').refresh();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="returnHandler"/>
|
||||
<property name="returnHandler" onget="return this._returnHandler;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._returnHandler = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="_parentItem"/>
|
||||
<property name="parentItem" onget="return this._parentItem;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._parentItem = this._id('links-box').parentItem = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="_item"/>
|
||||
<property name="item" onget="return this._item;">
|
||||
<setter><![CDATA[
|
||||
// The binding can be immediately destroyed
|
||||
// (which i.e. happens in merge dialog)
|
||||
if (this._destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._item && this._item.id && this._item.id === val.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._editorInstance) {
|
||||
this._editorInstance.uninit();
|
||||
this._editorInstance = null;
|
||||
}
|
||||
|
||||
this._lastHtmlValue = val.note;
|
||||
this._item = val;
|
||||
|
||||
// var parentKey = this._item.parentKey;
|
||||
// if (parentKey) {
|
||||
// this.parentItem = Zotero.Items.getByLibraryAndKey(this._item.libraryID, parentKey);
|
||||
// }
|
||||
|
||||
this._id('links-box').item = this._item;
|
||||
|
||||
(async () => {
|
||||
// `item` field can be set before the constructor is called
|
||||
// or noteeditor is attached to dom (which happens in the
|
||||
// merge dialog i.e.), therefore we wait for the initialization
|
||||
let n = 0;
|
||||
while (!this._initialized && !this._destroyed) {
|
||||
if (n >= 1000) {
|
||||
throw new Error('Waiting for noteeditor initialization failed');
|
||||
}
|
||||
await Zotero.Promise.delay(10);
|
||||
n++;
|
||||
}
|
||||
|
||||
if (this._destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initEditor();
|
||||
this._id('links-box').item = this._item;
|
||||
})();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="linksOnTop">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
// if (val) {
|
||||
// var container = this._id('links-container');
|
||||
// var parent = container.parentNode;
|
||||
// var sib = container.nextSibling;
|
||||
// while (parent.firstChild !== container) {
|
||||
// parent.insertBefore(parent.removeChild(parent.firstChild), sib);
|
||||
// }
|
||||
// }
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="navigateHandler">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
if (this._editorInstance) {
|
||||
this._editorInstance.onNavigate = val;
|
||||
}
|
||||
this._navigateHandler = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="hideLinksContainer">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._hideLinksContainer = val;
|
||||
this._id('links-container').hidden = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<field name="collection"/>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Zotero.Notifier.unregisterObserver(this._notifierID);
|
||||
if (this._editorInstance) {
|
||||
this._editorInstance.uninit();
|
||||
}
|
||||
this._destroyed = true;
|
||||
this._initialized = false;
|
||||
this._editorInstance = null;
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
<method name="save">
|
||||
<body><![CDATA[
|
||||
return (async () => {
|
||||
|
||||
})();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
<![CDATA[
|
||||
(async () => {
|
||||
let n = 0;
|
||||
while (!this._editorInstance && n++ < 100) {
|
||||
await Zotero.Promise.delay(10);
|
||||
}
|
||||
await this._editorInstance._initPromise;
|
||||
this._iframe.focus();
|
||||
this._editorInstance.focus();
|
||||
})();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="focusFirst">
|
||||
<body>
|
||||
<![CDATA[
|
||||
(async () => {
|
||||
try {
|
||||
let n = 0;
|
||||
while (!this._editorInstance && n++ < 100) {
|
||||
await Zotero.Promise.delay(10);
|
||||
}
|
||||
await this._editorInstance._initPromise;
|
||||
this._iframe.focus();
|
||||
this._editorInstance._iframeWindow.document.querySelector('.toolbar-button-return').focus();
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
})();
|
||||
]]>
|
||||
</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" style="display: flex;flex-direction: column;flex-grow: 1;">
|
||||
<!-- Notice: Update query selector for `iframe[anonid="editor-view"]` in contextPane.js if updating this -->
|
||||
<xul:iframe tooltip="editor-tooltip" anonid="editor-view" flex="1" overflow="auto" style="border: 0;width: 100%;flex-grow: 1;"
|
||||
frameBorder="0" src="resource://zotero/note-editor/editor.html" type="content"/>
|
||||
<xul:hbox id="links-container" hidden="true">
|
||||
<xul:linksbox id="links-box" flex="1" xbl:inherits="notitle"/>
|
||||
</xul:hbox>
|
||||
|
||||
<xul:popupset>
|
||||
<xul:tooltip id="editor-tooltip" onpopupshowing="return fillTooltip(this);"/>
|
||||
<xul:menupopup anonid="editor-menu" id="editor-menu" flex="1">
|
||||
</xul:menupopup>
|
||||
</xul:popupset>
|
||||
</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.id('related').item = this.item;
|
||||
this.refresh();
|
||||
|
||||
// Hide popup to prevent it being visible out of the context or
|
||||
// in some cases even invisible but still blocking the next click
|
||||
this.id('relatedPopup').addEventListener('click', (event) => {
|
||||
let target = event.originalTarget;
|
||||
if (target.classList.contains('zotero-box-label')) {
|
||||
this.id('relatedPopup').hidePopup();
|
||||
}
|
||||
});
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<property name="mode">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this.id('related').mode = val;
|
||||
this.id('tags').mode = val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<field name="_parentItem"/>
|
||||
<property name="parentItem" onget="return this._parentItem;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._parentItem = val;
|
||||
|
||||
var parentText = this.id('parentText');
|
||||
if (parentText.firstChild) {
|
||||
parentText.removeChild(parentText.firstChild);
|
||||
}
|
||||
|
||||
if (this._parentItem && this.getAttribute('notitle') != '1') {
|
||||
this.id('parent-row').hidden = undefined;
|
||||
this.id('parentLabel').value = Zotero.getString('pane.item.parentItem');
|
||||
parentText.appendChild(document.createTextNode(this._parentItem.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);
|
||||
|
||||
// If editable and no existing tags, open new empty row
|
||||
var tagsBox = this.id('tags');
|
||||
if (tagsBox.mode == 'edit' && tagsBox.count == 0) {
|
||||
this.id('tags').newTag();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="refresh">
|
||||
<body><![CDATA[
|
||||
this.updateTagsSummary();
|
||||
this.updateRelatedSummary();
|
||||
]]></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="relatedClick">
|
||||
<body><![CDATA[
|
||||
var relatedList = this.item.relatedItems;
|
||||
if (relatedList.length > 0) {
|
||||
var x = this.boxObject.screenX;
|
||||
var y = this.boxObject.screenY;
|
||||
this.id('relatedPopup').openPopupAtScreen(x, y, false);
|
||||
}
|
||||
else {
|
||||
this.id('related').add();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="updateRelatedSummary">
|
||||
<body><![CDATA[
|
||||
var v = this.id('related').summary;
|
||||
|
||||
if (!v || v == "") {
|
||||
v = "[" + Zotero.getString('pane.item.noteEditor.clickHere') + "]";
|
||||
}
|
||||
|
||||
this.id('relatedLabel').value = Zotero.getString('itemFields.related')
|
||||
+ Zotero.getString('punctuation.colon');
|
||||
this.id('relatedClick').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;
|
||||
}
|
||||
|
||||
Zotero.spawn(function* () {
|
||||
var parentID = this.item.parentID;
|
||||
yield zp.clearQuicksearch();
|
||||
zp.selectItem(parentID);
|
||||
}, this);
|
||||
]]>
|
||||
</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="relatedLabel"/>
|
||||
<xul:label id="relatedClick" class="zotero-clicky" crop="end"
|
||||
onclick="document.getBindingParent(this).relatedClick();"/>
|
||||
</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="relatedPopup" width="300" onpopupshowing="this.firstChild.refresh();">
|
||||
<xul:relatedbox id="related" 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>
|
1358
chrome/content/zotero/bindings/preferences-mac.xml
Normal file
1358
chrome/content/zotero/bindings/preferences-unix.xml
Normal file
1358
chrome/content/zotero/bindings/preferences-win.xml
Normal file
360
chrome/content/zotero/bindings/relatedbox.xml
Normal file
|
@ -0,0 +1,360 @@
|
|||
<?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="related-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.refresh();
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<property name="summary">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var r = "";
|
||||
|
||||
if (this.item) {
|
||||
var keys = this.item.relatedItems;
|
||||
if (keys.length) {
|
||||
for (let key of keys) {
|
||||
let item = Zotero.Items.getByLibraryAndKey(this.item.libraryID, key);
|
||||
if (!item) {
|
||||
Zotero.debug(`Related item ${this.item.libraryID}/${key} not found `
|
||||
+ `for item ${this.item.libraryKey}`, 2);
|
||||
continue;
|
||||
}
|
||||
r = r + item.getDisplayTitle() + ", ";
|
||||
}
|
||||
r = r.substr(0,r.length-2);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'relatedbox');
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Zotero.Notifier.unregisterObserver(this._notifierID);
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
<!-- TODO: Asyncify -->
|
||||
<method name="notify">
|
||||
<parameter name="event"/>
|
||||
<parameter name="type"/>
|
||||
<parameter name="ids"/>
|
||||
<parameter name="extraData"/>
|
||||
<body><![CDATA[
|
||||
if (!this.item || !this.item.id) return;
|
||||
|
||||
// Refresh if this item has been modified
|
||||
if (event == 'modify' && ids.includes(this.item.id)) {
|
||||
this.refresh();
|
||||
return;
|
||||
}
|
||||
|
||||
// Or if any listed items have been modified or deleted
|
||||
if (event == 'modify' || event == 'delete') {
|
||||
let libraryID = this.item.libraryID;
|
||||
let relatedItemIDs = new Set(this.item.relatedItems
|
||||
.map(key => Zotero.Items.getIDFromLibraryAndKey(libraryID, key)));
|
||||
for (let id of ids) {
|
||||
if (relatedItemIDs.has(id)) {
|
||||
this.refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="refresh">
|
||||
<body><![CDATA[
|
||||
var addButton = this.id('addButton');
|
||||
addButton.hidden = !this.editable;
|
||||
|
||||
var rows = this.id('relatedRows');
|
||||
while(rows.hasChildNodes())
|
||||
rows.removeChild(rows.firstChild);
|
||||
|
||||
if (this.item) {
|
||||
var relatedKeys = this.item.relatedItems;
|
||||
for (var i = 0; i < relatedKeys.length; i++) {
|
||||
let key = relatedKeys[i];
|
||||
let relatedItem = Zotero.Items.getByLibraryAndKey(
|
||||
this.item.libraryID, key
|
||||
);
|
||||
if (!relatedItem) {
|
||||
Zotero.debug(`Related item ${this.item.libraryID}/${key} not found `
|
||||
+ `for item ${this.item.libraryKey}`, 2);
|
||||
continue;
|
||||
}
|
||||
let id = relatedItem.id;
|
||||
let icon = document.createElement("image");
|
||||
icon.className = "zotero-box-icon";
|
||||
icon.setAttribute('src', relatedItem.getImageSrc());
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.className = "zotero-box-label";
|
||||
label.setAttribute('value', relatedItem.getDisplayTitle());
|
||||
label.setAttribute('crop','end');
|
||||
label.setAttribute('flex','1');
|
||||
|
||||
var box = document.createElement('box');
|
||||
box.setAttribute('onclick',
|
||||
"document.getBindingParent(this).showItem(" + 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(" + id + ");");
|
||||
remove.setAttribute('class','zotero-clicky zotero-clicky-minus');
|
||||
}
|
||||
|
||||
var row = document.createElement("row");
|
||||
row.appendChild(box);
|
||||
if (this.editable) {
|
||||
row.appendChild(remove);
|
||||
}
|
||||
rows.appendChild(row);
|
||||
}
|
||||
this.updateCount(rows.childNodes.length);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="add">
|
||||
<body><![CDATA[
|
||||
return Zotero.spawn(function* () {
|
||||
var io = {dataIn: null, dataOut: null, deferred: Zotero.Promise.defer()};
|
||||
|
||||
window.openDialog('chrome://zotero/content/selectItemsDialog.xul', '',
|
||||
'chrome,dialog=no,centerscreen,resizable=yes', io);
|
||||
|
||||
yield io.deferred.promise;
|
||||
|
||||
if (!io.dataOut || !io.dataOut.length) {
|
||||
return;
|
||||
}
|
||||
var relItems = yield Zotero.Items.getAsync(io.dataOut);
|
||||
if (!relItems.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (relItems[0].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.");
|
||||
return;
|
||||
}
|
||||
yield Zotero.DB.executeTransaction(function* () {
|
||||
for (let relItem of relItems) {
|
||||
if (this.item.addRelatedItem(relItem)) {
|
||||
yield this.item.save({
|
||||
skipDateModifiedUpdate: true
|
||||
});
|
||||
}
|
||||
if (relItem.addRelatedItem(this.item)) {
|
||||
yield relItem.save({
|
||||
skipDateModifiedUpdate: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}, this);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="remove">
|
||||
<parameter name="id"/>
|
||||
<body><![CDATA[
|
||||
return Zotero.spawn(function* () {
|
||||
var item = yield Zotero.Items.getAsync(id);
|
||||
if (item) {
|
||||
yield Zotero.DB.executeTransaction(function* () {
|
||||
if (this.item.removeRelatedItem(item)) {
|
||||
yield this.item.save({
|
||||
skipDateModifiedUpdate: true
|
||||
});
|
||||
}
|
||||
if (item.removeRelatedItem(this.item)) {
|
||||
yield item.save({
|
||||
skipDateModifiedUpdate: true
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}, this);
|
||||
]]></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.relatedItems.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('relatedNum').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>
|
||||
|
||||
<method name="receiveKeyboardFocus">
|
||||
<parameter name="direction" />
|
||||
<body><![CDATA[
|
||||
this.id("addButton").focus();
|
||||
// TODO: the relatedbox is not currently keyboard accessible
|
||||
// so we are ignoring the direction
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
<content>
|
||||
<xul:vbox xbl:inherits="flex" class="zotero-box">
|
||||
<xul:hbox align="center">
|
||||
<xul:label id="relatedNum"/>
|
||||
<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="relatedRows"/>
|
||||
</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>
|
807
chrome/content/zotero/bindings/styled-textbox.xml
Normal file
|
@ -0,0 +1,807 @@
|
|||
<?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="_changed"/>
|
||||
<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");
|
||||
|
||||
// Atomic units, HTML -> RTF (cleanup)
|
||||
//[/<\/p>(?!\s*$)/g, "\\par{}"],
|
||||
//[/ /g, " "],
|
||||
//[/\u00A0/g, " "],
|
||||
this._htmlRTFmap = [
|
||||
[/<br \/>/g, "\x0B"],
|
||||
[/<span class=\"tab\"> <\/span>/g, "\\tab{}"],
|
||||
[/‘/g, "‘"],
|
||||
[/’/g, "’"],
|
||||
[/“/g, "“"],
|
||||
[/”/g, "”"],
|
||||
[/ /g, "\u00A0"],
|
||||
[/"(\w)/g, "“$1"],
|
||||
[/([\w,.?!])"/g, "$1”"],
|
||||
[/<p>/g, ""],
|
||||
[/<\/?div[^>]*>/g, ""]
|
||||
];
|
||||
|
||||
// Atomic units, RTF -> HTML (cleanup)
|
||||
this._rtfHTMLmap = [
|
||||
[/\\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.prepare = function() {
|
||||
// DEBUG: Does this actually happen?
|
||||
if (this.prepared) 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 normalizeRegExpString(str) {
|
||||
if (!str) return str;
|
||||
return str.replace(/\s+/g, " ")
|
||||
.replace(/(?:[\+]|\s[\*])/g, "")
|
||||
.replace(/[\']/g, '\"')
|
||||
.replace(/:\s/g, ":");
|
||||
}
|
||||
|
||||
this.normalizeRegExpString = normalizeRegExpString;
|
||||
|
||||
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 primaryVal = normalizeRegExpString(_rexData[i][0][segment][0]);
|
||||
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
|
||||
var key = normalizeRegExpString(_rexData[i][0][segment][j]);
|
||||
ret[key] = primaryVal;
|
||||
}
|
||||
}
|
||||
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 primaryVal = _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[primaryVal] = 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 primaryVal = normalizeRegExpString(_rexData[i][0][segment][0]);
|
||||
ret[primaryVal] = {
|
||||
open: normalizeRegExpString(_rexData[i][0][antisegment][0]),
|
||||
close: _rexData[i][1][antisegment][0]
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.rtfHTMLtagRegistry = tagRegistryMaker(1);
|
||||
this.htmlRTFtagRegistry = tagRegistryMaker(0);
|
||||
|
||||
this.prepared = true;
|
||||
}
|
||||
this.prepare();
|
||||
|
||||
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"][this.normalizeRegExpString(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) {
|
||||
txt = this.convert("htmlRTF", 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 = Zotero.Utilities.unescapeHTML(txt);
|
||||
txt = txt.replace(/[\x7F-\uFFFF]/g, function(aChar) { return "\\uc0\\u"+aChar.charCodeAt(0).toString()+"{}"});
|
||||
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':
|
||||
this._eventHandler = function (event) {
|
||||
// Necessary in Fx32+
|
||||
if (event.wrappedJSObject) {
|
||||
event = event.wrappedJSObject;
|
||||
}
|
||||
|
||||
var commandEvent = false;
|
||||
|
||||
if (Zotero.Prefs.get('debugNoteEvents')) {
|
||||
Zotero.debug(event.type);
|
||||
Zotero.debug(event.which);
|
||||
}
|
||||
switch (event.type) {
|
||||
case 'keydown':
|
||||
// Handle forward-delete, which doesn't register as a keypress
|
||||
// when a selection is cleared
|
||||
if (event.which == event.DOM_VK_DELETE) {
|
||||
this._changed = true;
|
||||
commandEvent = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'keypress':
|
||||
// Ignore keypresses that don't change
|
||||
// any text
|
||||
//Zotero.debug(event.which);
|
||||
if (!event.which &&
|
||||
event.keyCode != event.DOM_VK_DELETE &&
|
||||
event.keyCode != event.DOM_VK_BACK_SPACE) {
|
||||
//Zotero.debug("Not a char");
|
||||
return;
|
||||
}
|
||||
this._changed = true;
|
||||
commandEvent = true;
|
||||
break;
|
||||
|
||||
// 'change' includes text added via drag-and-drop
|
||||
case 'change':
|
||||
case 'undo':
|
||||
case 'redo':
|
||||
this._changed = true;
|
||||
commandEvent = true;
|
||||
break;
|
||||
|
||||
case 'ZoteroLinkClick':
|
||||
var zp = typeof ZoteroPane != 'undefined'
|
||||
? ZoteroPane
|
||||
: window.opener.ZoteroPane;
|
||||
zp.loadURI(event.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger command on change
|
||||
if (commandEvent && this.timeout) {
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
|
||||
this._timer = setTimeout(function () {
|
||||
var attr = this.getAttribute('oncommand');
|
||||
attr = attr.replace('this', 'thisObj');
|
||||
var func = new Function('thisObj', 'event', attr);
|
||||
func(this, event);
|
||||
}.bind(this), this.timeout);
|
||||
}
|
||||
|
||||
return true;
|
||||
}.bind(this);
|
||||
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[
|
||||
if (!this._editor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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 ;
|
||||
}
|
||||
|
||||
// Hack to ignore incomplete editors due to rapid note creation in tests
|
||||
if (Zotero.test && !this._editor.getContent) {
|
||||
Zotero.logError("editor.getContent doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.value == val) {
|
||||
Zotero.debug("Textbox value hasn't changed");
|
||||
this._changed = false;
|
||||
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>";
|
||||
}
|
||||
|
||||
Zotero.debug("Setting content to " + html);
|
||||
|
||||
this._editor.setContent(html);
|
||||
this._changed = false;
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="timeout"
|
||||
onset="this.setAttribute('timeout', val); return val;"
|
||||
onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
|
||||
|
||||
<property name="changed" onget="return this._changed;" onset="this._changed = !!val;"/>
|
||||
|
||||
<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="hasFocus">
|
||||
<body>
|
||||
<![CDATA[
|
||||
return this._editor ? this._editor.hasFocus() : false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="clearUndo">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._editor) {
|
||||
this._editor.undoManager.clear();
|
||||
this._editor.undoManager.add();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="onInit">
|
||||
<parameter name="callback"/>
|
||||
<body><![CDATA[
|
||||
if (this.initialized) {
|
||||
// Hack to ignore incomplete editors due to rapid note creation in tests
|
||||
if (Zotero.test && !this._editor.setMode) {
|
||||
Zotero.logError("editor.setMode doesn't exist after initialization");
|
||||
return;
|
||||
}
|
||||
callback(this._editor);
|
||||
}
|
||||
else {
|
||||
if (!this._onInitCallbacks) {
|
||||
this._onInitCallbacks = [];
|
||||
}
|
||||
this._onInitCallbacks.push(callback);
|
||||
}
|
||||
]]></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 url = `resource://zotero/tinymce/${htmlFile}.html`
|
||||
// Pass directionality (LTR/RTL) and locale in URL
|
||||
+ "?locale=" + encodeURIComponent(Zotero.locale)
|
||||
+ "&dir=" + Zotero.dir;
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
var uri = Services.io.newURI(url, null, null);
|
||||
|
||||
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) {
|
||||
Zotero.getInstalledExtensions().then(function(exts) {
|
||||
for (let ext of 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;
|
||||
|
||||
// Prevent undoing to empty note after initialization
|
||||
self._editor.undoManager.clear();
|
||||
self._editor.undoManager.add();
|
||||
}
|
||||
if (self._focus) {
|
||||
setTimeout(function () {
|
||||
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, "
|
||||
+ "body#zotero-tinymce-note p, "
|
||||
+ "body#zotero-tinymce-note th, "
|
||||
+ "body#zotero-tinymce-note td, "
|
||||
+ "body#zotero-tinymce-note pre { "
|
||||
+ "font-size: " + fontSize + "px; "
|
||||
+ "} "
|
||||
+ "body#zotero-tinymce-note, "
|
||||
+ "body#zotero-tinymce-note 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);
|
||||
}
|
||||
|
||||
let cb;
|
||||
if (this._onInitCallbacks) {
|
||||
while (cb = this._onInitCallbacks.shift()) {
|
||||
// Hack to ignore incomplete editors due to rapid note creation in tests
|
||||
if (Zotero.test && !this._editor.setMode) {
|
||||
Zotero.logError("editor.setMode doesn't exist");
|
||||
return;
|
||||
}
|
||||
cb(this._editor);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
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>
|
1183
chrome/content/zotero/bindings/tagsbox.xml
Normal file
123
chrome/content/zotero/bindings/text-link.xml
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?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.defaultPrevented)
|
||||
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;
|
||||
}
|
||||
|
||||
// Open HTTP URLs externally
|
||||
if (window.Zotero && ["http", "https"].includes(uri.scheme)) {
|
||||
Zotero.launchURL(uri.spec);
|
||||
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>
|
1112
chrome/content/zotero/bindings/zoterosearch.xml
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();
|
||||
}
|
||||
}
|