Add global music player, invoicing/payment system, account subpages, mail account admin, and the qualityiron.vegas Jet 2.0 port
Jet interpreter (Tag.cpp, __call.cpp, __imap*.cpp/h, __smtpsend.cpp/h, __imapemptyfolder.cpp/h - new): assorted parser/tag fixes found across this work - a stray literal-tag-in-comment and backslash-quote parser corruption class, a dangling-pointer fix, a __call.cpp fd leak, IMAP folder-management tags, multi-account/per-host IMAP support, and a smtpsend Message-ID fix. barant.com site (jetc/barant-site/): - A site-wide persistent music player (header band, playlist/queue, stereo FFT EQ, session-persisted state) fed by new library/ ianslibrary/music song-list subpages. - /account split into info/phones/invoices subpages; a full invoicing and Square payment system (create/edit/copy/pay/email invoice); admin invoice management and mail-account management subpages. - /services split into overview/hosting/siptrunking/documents subpages, retiring the old standalone pages. - SIPPHONE.tag: a Jet 2.0 WebRTC softphone tag. - main.css/spa.js/email.js: the SPA loading indicator, the music player band styling, and assorted fixes accumulated alongside this work. qualityiron-site/: the qualityiron.vegas job/contractor/customer/ document management app, ported from its original Jet 1.4 codebase to Jet 2.0 as barant.coms APIServers second multi-tenant site. wcwc/wcwc.jet: the WCWC site Jet source (wcwc.jtc build output not included). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
905fbafa5a
commit
b8f7793773
406 files changed
+15742
-526
No files matched your search
@@ -11,6 +11,7 @@
|
||||
#include "__imapmessage.h"
|
||||
#include "__imapflag.h"
|
||||
#include "__imapdelete.h"
|
||||
#include "__imapemptyfolder.h"
|
||||
#include "__imapmove.h"
|
||||
#include "__imapfolders.h"
|
||||
#include "__imapsearch.h"
|
||||
@@ -215,9 +216,33 @@ namespace jet {
|
||||
// matches the same unconsumed <catch> on every subsequent
|
||||
// iteration forever. Build the real expected delimiter
|
||||
// from splitTagName itself so it works for any split tag.
|
||||
coreutils::MString splitOpenTag;
|
||||
splitOpenTag << "<" << splitTagName << ">";
|
||||
in.ifNextIgnoreCase(splitOpenTag);
|
||||
in.ifNext("<");
|
||||
in.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
|
||||
while(!in.eod()) {
|
||||
in.skipWhitespace();
|
||||
if(in.ifNext(">"))
|
||||
break;
|
||||
else if(in.getTokenExclude("=").getLength() != 0) {
|
||||
bool dq = in.ifNext("=\"");
|
||||
bool sq = !dq && in.ifNext("='");
|
||||
if(dq || sq) {
|
||||
while(1) {
|
||||
if(in.ifNext(dq ? "\"" : "'"))
|
||||
break;
|
||||
in.nextChar();
|
||||
}
|
||||
} else {
|
||||
in.nextChar();
|
||||
while(!in.eod()) {
|
||||
char c = in.charAt(0);
|
||||
if(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '>' || c == '/')
|
||||
break;
|
||||
in.nextChar();
|
||||
}
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
start = in.getCursor();
|
||||
} else if(ifNested(in)) {
|
||||
} else
|
||||
@@ -477,6 +502,9 @@ namespace jet {
|
||||
} else if(ifTagName(in, "imapdelete")) {
|
||||
__imapdelete _imapdelete(in, out, global, this, local);
|
||||
continue;
|
||||
} else if(ifTagName(in, "imapemptyfolder")) {
|
||||
__imapemptyfolder _imapemptyfolder(in, out, global, this, local);
|
||||
continue;
|
||||
} else if(ifTagName(in, "imapmove")) {
|
||||
__imapmove _imapmove(in, out, global, this, local);
|
||||
continue;
|
||||
@@ -737,11 +765,48 @@ namespace jet {
|
||||
|
||||
bool Tag::ifSplitTagName(coreutils::ZString &in) {
|
||||
in.push();
|
||||
if(in.ifNext("<"))
|
||||
if(in.ifNext("<")) {
|
||||
if(coreutils::MString(in.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_")).toLower() == coreutils::MString(splitTagName).toLower()) {
|
||||
if(in.ifNext(">"))
|
||||
// Tolerate attributes on the split-tag marker itself (e.g.
|
||||
// <try>'s own <catch name="_imaperr">) rather than requiring
|
||||
// '>' to land immediately after the tag name - every
|
||||
// splitTagName="else" caller writes a bare <else> so this
|
||||
// never mattered for them, but <catch name="..."> is the
|
||||
// universal convention everywhere it's used. Previously this
|
||||
// whole check was a single unbraced
|
||||
// if(...){in.pop();return true;} where the missing braces
|
||||
// meant "return true" executed unconditionally, leaving the
|
||||
// cursor in a half-advanced, never-popped state on the
|
||||
// attributed-tag path - confirmed live via a real /email/list
|
||||
// failure whose caught error text leaked
|
||||
// "name=\"_imaperr\">" into the JSON response.
|
||||
while(!in.eod()) {
|
||||
in.skipWhitespace();
|
||||
if(in.ifNext(">")) {
|
||||
in.pop();
|
||||
return true;
|
||||
} else if(in.getTokenExclude("=").getLength() != 0) {
|
||||
bool dq = in.ifNext("=\"");
|
||||
bool sq = !dq && in.ifNext("='");
|
||||
if(dq || sq) {
|
||||
while(1) {
|
||||
if(in.ifNext(dq ? "\"" : "'"))
|
||||
break;
|
||||
in.nextChar();
|
||||
}
|
||||
} else {
|
||||
in.nextChar();
|
||||
while(!in.eod()) {
|
||||
char c = in.charAt(0);
|
||||
if(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '>' || c == '/')
|
||||
break;
|
||||
in.nextChar();
|
||||
}
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
in.pop();
|
||||
return false;
|
||||
|
||||
+57
-10
@@ -7,6 +7,8 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
|
||||
namespace jet {
|
||||
@@ -35,36 +37,69 @@ namespace jet {
|
||||
} else
|
||||
break;
|
||||
}
|
||||
pipe(fdo);
|
||||
// pipe()/fork() both used to go unchecked here - on failure (most
|
||||
// realistically pipe() hitting the process's open-file-descriptor
|
||||
// limit, see below) fdo[] is left holding whatever garbage was
|
||||
// already on the stack/in this member array, and every use of it
|
||||
// after this point (close(), read(), and - for a failed fork() -
|
||||
// waitpid(-1, ...), which has the special POSIX meaning "wait for
|
||||
// ANY child" rather than "wait for none") operates on that garbage
|
||||
// or on an unrelated process instead of safely no-oping. That's a
|
||||
// real, confirmed mechanism for exactly the kind of sporadic
|
||||
// memory corruption this codebase has seen: closing/reading a
|
||||
// stale fd that coincidentally matches another subsystem's live
|
||||
// socket, or reaping a concurrent request's own child out from
|
||||
// under it.
|
||||
if(pipe(fdo) != 0)
|
||||
throw coreutils::Exception("call: pipe() failed - " + std::string(strerror(errno)), __FILE__, __LINE__, 500);
|
||||
pid = fork();
|
||||
if(pid < 0) {
|
||||
close(fdo[0]);
|
||||
close(fdo[1]);
|
||||
throw coreutils::Exception("call: fork() failed - " + std::string(strerror(errno)), __FILE__, __LINE__, 500);
|
||||
}
|
||||
if(pid == 0) {
|
||||
close(fdo[0]);
|
||||
dup2(fdo[1], 1);
|
||||
if(hasContainer) {
|
||||
pipe(fdi);
|
||||
if(fork() == 0) {
|
||||
if(pipe(fdi) == 0) {
|
||||
pid_t innerPid = fork();
|
||||
if(innerPid == 0) {
|
||||
close(fdi[0]);
|
||||
write(fdi[1], container.getData(), container.getLength());
|
||||
close(fdi[1]);
|
||||
exit(0);
|
||||
}
|
||||
_exit(0);
|
||||
} else if(innerPid > 0) {
|
||||
close(fdi[1]);
|
||||
dup2(fdi[0], 0);
|
||||
close(fdi[0]);
|
||||
} else {
|
||||
close(fdi[0]);
|
||||
close(fdi[1]);
|
||||
}
|
||||
}
|
||||
} else if(keywordDefined("input")) {
|
||||
coreutils::MString input(resolveKeyword("input"));
|
||||
pipe(fdi);
|
||||
if(fork() == 0) {
|
||||
if(pipe(fdi) == 0) {
|
||||
pid_t innerPid = fork();
|
||||
if(innerPid == 0) {
|
||||
close(fdi[0]);
|
||||
write(fdi[1], input.getData(), input.getLength());
|
||||
close(fdi[1]);
|
||||
exit(0);
|
||||
}
|
||||
_exit(0);
|
||||
} else if(innerPid > 0) {
|
||||
close(fdi[1]);
|
||||
dup2(fdi[0], 0);
|
||||
close(fdi[0]);
|
||||
} else {
|
||||
close(fdi[0]);
|
||||
close(fdi[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = execvpe(argv[0], argv, global.envp);
|
||||
close(fdo[1]);
|
||||
exit(errno);
|
||||
_exit(errno);
|
||||
}
|
||||
close(fdo[1]);
|
||||
if(keywordDefined("name")) {
|
||||
@@ -73,6 +108,18 @@ namespace jet {
|
||||
storeVariable(resolveKeyword("name"), value, resolveKeyword("scope"));
|
||||
} else
|
||||
out.read(fdo[0]);
|
||||
// fdo[0] (the read end, still open in this - the parent - process)
|
||||
// was never closed here before, leaking one file descriptor on
|
||||
// every single <call> invocation for the life of the process.
|
||||
// Harmless-looking for an occasional <call>, but <call> is used
|
||||
// throughout this codebase (jq/curl parsing, mailcreate, this
|
||||
// session's own per-line-item JS-escaping on the invoice editor,
|
||||
// which alone can issue a double-digit number of calls per page
|
||||
// load) - repeated, routine use was slowly accumulating leaked
|
||||
// fds for as long as this process stayed up, eventually hitting
|
||||
// the real open-files limit and turning into exactly the pipe()
|
||||
// failures (and the undefined behavior above) this fix addresses.
|
||||
close(fdo[0]);
|
||||
waitpid(pid, &status, 0);
|
||||
if(keywordDefined("error")) {
|
||||
global.variables[resolveKeyword("error")] = (status >> 8 & 255);
|
||||
|
||||
+27
-2
@@ -559,8 +559,15 @@ namespace jet {
|
||||
coreutils::MString passwordVal = resolveKeyword("password");
|
||||
|
||||
coreutils::JFile config(configPath);
|
||||
std::string host = config.getString("host");
|
||||
long port = (long)config.getNumber("port");
|
||||
// host/port keywords override the config file's own values when
|
||||
// present - lets a caller reuse one config file (still needed for
|
||||
// caCertificate/smtpPort) across many accounts that each live on
|
||||
// a different mail server, rather than requiring a separate config
|
||||
// file per server. Every existing caller omits these keywords, so
|
||||
// behavior is unchanged for them - config's own host/port is still
|
||||
// the only thing read in that case.
|
||||
std::string host = keywordDefined("host") ? resolveKeyword("host").str() : config.getString("host");
|
||||
long port = keywordDefined("port") ? strtol(resolveKeyword("port").str().c_str(), nullptr, 10) : (long)config.getNumber("port");
|
||||
if (port <= 0)
|
||||
port = 993;
|
||||
|
||||
@@ -1034,6 +1041,24 @@ namespace jet {
|
||||
return coreutils::MString(std::string("{\"ok\":") + (ok ? "true" : "false") + "}");
|
||||
}
|
||||
|
||||
coreutils::MString __imap::emptyFolder(const std::string &folder) {
|
||||
if (!selectFolderIfNeeded(folder))
|
||||
throw coreutils::Exception("imap: could not select folder " + folder, __FILE__, __LINE__, 502);
|
||||
|
||||
std::string tag = nextTag();
|
||||
sendLine(tag + " UID STORE 1:* +FLAGS (\\Deleted)");
|
||||
auto lines = readUntilTagged(tag);
|
||||
bool ok1 = taggedOk(lines, tag);
|
||||
|
||||
std::string tag2 = nextTag();
|
||||
sendLine(tag2 + " EXPUNGE");
|
||||
auto lines2 = readUntilTagged(tag2);
|
||||
bool ok2 = taggedOk(lines2, tag2);
|
||||
|
||||
bool ok = ok1 && ok2;
|
||||
return coreutils::MString(std::string("{\"ok\":") + (ok ? "true" : "false") + "}");
|
||||
}
|
||||
|
||||
// BARANTMail (see __IMAP_COPY.cpp) implements COPY but not the
|
||||
// RFC 6851 MOVE extension - not surprising, since the whole point
|
||||
// of that extension was standardizing what every real-world client
|
||||
|
||||
@@ -63,6 +63,15 @@ namespace jet {
|
||||
coreutils::MString setFlag(const std::string &folder, uint32_t uid, const std::string &flag, bool add);
|
||||
coreutils::MString deleteMessage(const std::string &folder, uint32_t uid);
|
||||
coreutils::MString moveMessage(const std::string &folder, uint32_t uid, const std::string &destFolder);
|
||||
// Permanently empties an entire folder - every message, not one at
|
||||
// a time. "1:*" is IMAP's standard UID-range syntax for "every UID
|
||||
// in the selected mailbox" (well-defined and a no-op, not an error,
|
||||
// on an already-empty folder - verified directly against
|
||||
// BARANTMail rather than assumed from the RFC), so this is a
|
||||
// single mark-all-deleted STORE plus one EXPUNGE, not a loop over
|
||||
// deleteMessage() - the whole point is one IMAP round trip instead
|
||||
// of one per message.
|
||||
coreutils::MString emptyFolder(const std::string &folder);
|
||||
coreutils::MString folderCounts();
|
||||
|
||||
coreutils::MString sessionId;
|
||||
|
||||
+43
-19
@@ -37,8 +37,8 @@ namespace jet {
|
||||
return s.substr(start, end - start + 1);
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> __imapaccounts::decodeList(const std::string &encodedRaw) {
|
||||
std::vector<std::pair<std::string, std::string>> entries;
|
||||
std::vector<__imapaccounts::Account> __imapaccounts::decodeList(const std::string &encodedRaw) {
|
||||
std::vector<Account> entries;
|
||||
coreutils::Base64 base64;
|
||||
// The list value round-trips through <eval>/<set> template
|
||||
// captures, which include whatever whitespace/newlines surround
|
||||
@@ -56,26 +56,35 @@ namespace jet {
|
||||
entry = trimWhitespace(entry);
|
||||
if (entry.empty())
|
||||
continue;
|
||||
size_t colon = entry.find(':');
|
||||
if (colon == std::string::npos)
|
||||
size_t colon1 = entry.find(':');
|
||||
if (colon1 == std::string::npos)
|
||||
continue;
|
||||
std::string userB64 = trimWhitespace(entry.substr(0, colon));
|
||||
std::string passB64 = trimWhitespace(entry.substr(colon + 1));
|
||||
std::string user = base64.decode(userB64).str();
|
||||
std::string password = base64.decode(passB64).str();
|
||||
entries.push_back(std::make_pair(user, password));
|
||||
size_t colon2 = entry.find(':', colon1 + 1);
|
||||
if (colon2 == std::string::npos)
|
||||
continue;
|
||||
std::string hostB64 = trimWhitespace(entry.substr(0, colon1));
|
||||
std::string userB64 = trimWhitespace(entry.substr(colon1 + 1, colon2 - colon1 - 1));
|
||||
std::string passB64 = trimWhitespace(entry.substr(colon2 + 1));
|
||||
Account account;
|
||||
account.host = base64.decode(hostB64).str();
|
||||
account.user = base64.decode(userB64).str();
|
||||
account.password = base64.decode(passB64).str();
|
||||
entries.push_back(account);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
std::string __imapaccounts::encodeList(const std::vector<std::pair<std::string, std::string>> &entries) {
|
||||
std::string __imapaccounts::encodeList(const std::vector<Account> &entries) {
|
||||
coreutils::Base64 base64;
|
||||
std::string result;
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if (i > 0)
|
||||
result += ";";
|
||||
std::string user = entries[i].first;
|
||||
std::string password = entries[i].second;
|
||||
std::string host = entries[i].host;
|
||||
std::string user = entries[i].user;
|
||||
std::string password = entries[i].password;
|
||||
result += base64.encode(host).str();
|
||||
result += ":";
|
||||
result += base64.encode(user).str();
|
||||
result += ":";
|
||||
result += base64.encode(password).str();
|
||||
@@ -90,20 +99,25 @@ namespace jet {
|
||||
auto entries = decodeList(listStr);
|
||||
|
||||
if (action == "add") {
|
||||
std::string host = trimWhitespace(resolveKeyword("host").str());
|
||||
std::string user = trimWhitespace(resolveKeyword("user").str());
|
||||
std::string password = trimWhitespace(resolveKeyword("password").str());
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if (entries[i].first == user) {
|
||||
if (entries[i].user == user) {
|
||||
entries.erase(entries.begin() + (long)i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
entries.push_back(std::make_pair(user, password));
|
||||
Account account;
|
||||
account.host = host;
|
||||
account.user = user;
|
||||
account.password = password;
|
||||
entries.push_back(account);
|
||||
out = coreutils::MString(encodeList(entries));
|
||||
} else if (action == "remove") {
|
||||
std::string user = trimWhitespace(resolveKeyword("user").str());
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if (entries[i].first == user) {
|
||||
if (entries[i].user == user) {
|
||||
entries.erase(entries.begin() + (long)i);
|
||||
break;
|
||||
}
|
||||
@@ -113,21 +127,31 @@ namespace jet {
|
||||
std::string user = trimWhitespace(resolveKeyword("user").str());
|
||||
std::string password;
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if (entries[i].first == user) {
|
||||
password = entries[i].second;
|
||||
if (entries[i].user == user) {
|
||||
password = entries[i].password;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = coreutils::MString(password);
|
||||
} else if (action == "gethost") {
|
||||
std::string user = trimWhitespace(resolveKeyword("user").str());
|
||||
std::string host;
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if (entries[i].user == user) {
|
||||
host = entries[i].host;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = coreutils::MString(host);
|
||||
} else if (action == "firstuser") {
|
||||
out = coreutils::MString(entries.empty() ? std::string() : entries[0].first);
|
||||
out = coreutils::MString(entries.empty() ? std::string() : entries[0].user);
|
||||
} else if (action == "list") {
|
||||
std::string active = resolveKeyword("active").str();
|
||||
std::string json = "{\"accounts\":[";
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if (i > 0)
|
||||
json += ",";
|
||||
json += "\"" + jsonEscape(entries[i].first) + "\"";
|
||||
json += "\"" + jsonEscape(entries[i].user) + "\"";
|
||||
}
|
||||
json += "],\"active\":\"" + jsonEscape(active) + "\"}";
|
||||
out = coreutils::MString(json);
|
||||
|
||||
+24
-13
@@ -11,8 +11,8 @@
|
||||
namespace jet {
|
||||
|
||||
///
|
||||
/// <imapaccounts action="add|remove|getpassword|firstuser|list"
|
||||
/// list="$[@_imap_accounts]" user="..." password="...">
|
||||
/// <imapaccounts action="add|remove|getpassword|gethost|firstuser|list"
|
||||
/// list="$[@_imap_accounts]" host="..." user="..." password="...">
|
||||
///
|
||||
/// Pure list-transform tag (no session-variable access of its own,
|
||||
/// no IMAP connection) that manages the multi-account list webmail
|
||||
@@ -23,34 +23,45 @@ namespace jet {
|
||||
/// touches Global's session-variable map directly).
|
||||
///
|
||||
/// The list's own on-the-wire encoding (semicolon-separated
|
||||
/// "base64(user):base64(password)" entries) is private to this tag -
|
||||
/// callers only ever pass the whole `list` value back in verbatim
|
||||
/// and use the returned value the same way, so the choice of
|
||||
/// delimiter can't collide with any real username or password
|
||||
/// character.
|
||||
/// "base64(host):base64(user):base64(password)" entries) is private
|
||||
/// to this tag - callers only ever pass the whole `list` value back
|
||||
/// in verbatim and use the returned value the same way, so the
|
||||
/// choice of delimiter can't collide with any real username or
|
||||
/// password character. Each account can live on its own IMAP server
|
||||
/// (see the <imap>/<imaplist>/etc. tags' own optional host/port
|
||||
/// keywords), not just the one fixed host in email.cfg.
|
||||
///
|
||||
/// action="add": upserts user/password (removing any existing entry
|
||||
/// for the same user first, so reconnecting with a changed password
|
||||
/// updates it) - returns the updated encoded list.
|
||||
/// action="add": upserts host/user/password (removing any existing
|
||||
/// entry for the same user first, so reconnecting with a changed
|
||||
/// password or server updates it) - returns the updated encoded list.
|
||||
/// action="remove": drops the entry for user, if present - returns
|
||||
/// the updated encoded list.
|
||||
/// action="getpassword": returns the stored password for user, or
|
||||
/// an empty string if not present.
|
||||
/// action="gethost": returns the stored host for user, or an empty
|
||||
/// string if not present.
|
||||
/// action="firstuser": returns the first entry's username, or an
|
||||
/// empty string if the list is empty.
|
||||
/// action="list": returns JSON ({"accounts":[...],"active":"..."})
|
||||
/// - the one client-facing action; "active" echoes the `active`
|
||||
/// keyword (typically $[@_imap_user]) back verbatim so the sidebar
|
||||
/// can highlight the current one, and never includes any password.
|
||||
/// can highlight the current one, and never includes any password or
|
||||
/// host (unchanged shape from before per-account hosts existed -
|
||||
/// nothing client-side needs the host to switch between already-
|
||||
/// connected accounts).
|
||||
///
|
||||
class __imapaccounts : public Tag {
|
||||
|
||||
struct Account {
|
||||
std::string host, user, password;
|
||||
};
|
||||
|
||||
public:
|
||||
__imapaccounts(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local);
|
||||
|
||||
private:
|
||||
static std::vector<std::pair<std::string, std::string>> decodeList(const std::string &encoded);
|
||||
static std::string encodeList(const std::vector<std::pair<std::string, std::string>> &entries);
|
||||
static std::vector<Account> decodeList(const std::string &encoded);
|
||||
static std::string encodeList(const std::vector<Account> &entries);
|
||||
static std::string jsonEscape(const std::string &s);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "__imapemptyfolder.h"
|
||||
#include "Exception.h"
|
||||
#include "__imap.h"
|
||||
|
||||
namespace jet {
|
||||
|
||||
__imapemptyfolder::__imapemptyfolder(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, local) {
|
||||
|
||||
coreutils::MString sessionId = resolveKeyword("sessionid");
|
||||
if (!global.imapSessionExists(sessionId))
|
||||
throw coreutils::Exception("imap sessionid does not exist.", __FILE__, __LINE__, 502);
|
||||
|
||||
// Unlike __imapdelete (one message - low blast radius even on a
|
||||
// wrong default), this permanently destroys an entire folder's
|
||||
// contents - no silent "defaults to INBOX" here. A missing/blank
|
||||
// folder attribute is refused outright rather than risked.
|
||||
if (!keywordDefined("folder"))
|
||||
throw coreutils::Exception("imapemptyfolder tag must have folder defined.", __FILE__, __LINE__, 400);
|
||||
std::string folder = resolveKeyword("folder").str();
|
||||
if (folder.empty())
|
||||
throw coreutils::Exception("imapemptyfolder tag must have folder defined.", __FILE__, __LINE__, 400);
|
||||
|
||||
out = global.getImapSession(sessionId)->emptyFolder(folder);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef ____imapemptyfolder_h__
|
||||
# define ____imapemptyfolder_h__
|
||||
|
||||
# include "Tag.h"
|
||||
|
||||
namespace jet {
|
||||
|
||||
///
|
||||
/// <imapemptyfolder sessionid="" folder="Trash">
|
||||
///
|
||||
/// Self-closing tag - permanently deletes every message in the given
|
||||
/// folder (mark-all-\Deleted + one EXPUNGE, not a per-message loop),
|
||||
/// writes {"ok":true|false} into `out`. See __imaplist.h's doc
|
||||
/// comment for how `out` reaches the real response body.
|
||||
///
|
||||
|
||||
class __imapemptyfolder : public Tag {
|
||||
|
||||
public:
|
||||
__imapemptyfolder(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace jet {
|
||||
|
||||
@@ -88,10 +90,31 @@ namespace jet {
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// RFC 5322 3.6.4: Message-ID "SHOULD be present" - in practice
|
||||
// several real receivers (confirmed live: Gmail) now hard-reject
|
||||
// anything missing one ("550 5.7.1 Messages missing a valid
|
||||
// Message-ID header are not accepted") rather than just marking it
|
||||
// down, so this isn't optional in practice. Domain part is the
|
||||
// sender's own domain (everything after '@' in `from`), matching
|
||||
// RFC 5322's own recommendation that it be a name under the
|
||||
// generating system's control - falls back to the literal `from`
|
||||
// string in the (should-never-happen) case it has no '@' at all.
|
||||
std::string __smtpsend::generateMessageId(const std::string &from) {
|
||||
size_t at = from.find('@');
|
||||
std::string domainPart = (at == std::string::npos) ? from : from.substr(at + 1);
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
std::ostringstream idStream;
|
||||
idStream << ts.tv_sec << "." << std::setfill('0') << std::setw(9) << ts.tv_nsec
|
||||
<< "." << rand() << "@" << domainPart;
|
||||
return idStream.str();
|
||||
}
|
||||
|
||||
std::string __smtpsend::buildMessage(const std::string &from, const std::string &to,
|
||||
const std::string &subject, const std::string &html) {
|
||||
std::string msg;
|
||||
msg += "Date: " + rfc2822Date() + "\r\n";
|
||||
msg += "Message-ID: <" + generateMessageId(from) + ">\r\n";
|
||||
msg += "From: " + from + "\r\n";
|
||||
msg += "To: " + to + "\r\n";
|
||||
msg += "Subject: " + subject + "\r\n";
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace jet {
|
||||
|
||||
static std::string base64Encode(const std::string &s);
|
||||
static std::string rfc2822Date();
|
||||
static std::string generateMessageId(const std::string &from);
|
||||
// Builds the full RFC 5322 message (headers + dot-stuffed body)
|
||||
// handed to SMTP's DATA command.
|
||||
static std::string buildMessage(const std::string &from, const std::string &to,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 510 KiB |
@@ -43,6 +43,13 @@
|
||||
pageNext:
|
||||
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">' +
|
||||
'<path d="M9 18l6-6-6-6"/>' +
|
||||
'</svg>',
|
||||
emptyFolder:
|
||||
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">' +
|
||||
'<path d="M4 7h16"/>' +
|
||||
'<path d="M9 7V4h6v3"/>' +
|
||||
'<path d="M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13"/>' +
|
||||
'<path d="M9.5 12.5l5 5M14.5 12.5l-5 5"/>' +
|
||||
'</svg>'
|
||||
};
|
||||
|
||||
@@ -109,6 +116,15 @@
|
||||
var links = document.querySelectorAll('.email-folder-link');
|
||||
for (var i = 0; i < links.length; i++)
|
||||
links[i].classList.toggle('email-folder-selected', links[i].getAttribute('data-folder') === currentFolder);
|
||||
// Only Spam/Trash ever offer this - emptying Inbox (or any future
|
||||
// folder) as a single destructive click isn't something any real
|
||||
// mail client exposes, and the server enforces the exact same
|
||||
// Spam/Trash-only allowlist independently (see email.jet) - this is
|
||||
// just keeping the button from ever being visible somewhere it
|
||||
// would 400 anyway, not the actual safety boundary.
|
||||
var emptyBtn = document.getElementById('email-empty-folder-btn');
|
||||
if (emptyBtn)
|
||||
emptyBtn.hidden = (currentFolder !== 'Spam' && currentFolder !== 'Trash');
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
@@ -158,6 +174,7 @@
|
||||
'<button type="button" id="email-search-btn" class="icon-btn" title="Search">' + ICONS.search + '</button>' +
|
||||
'</span>' +
|
||||
'<button type="button" id="email-compose-btn" class="icon-btn" title="New Mail">' + ICONS.compose + '</button>' +
|
||||
'<button type="button" id="email-empty-folder-btn" class="icon-btn" title="Permanently empty this folder" hidden>' + ICONS.emptyFolder + '</button>' +
|
||||
'<button type="button" id="email-refresh-btn" class="icon-btn" title="Refresh">' + ICONS.refresh + '</button>' +
|
||||
'</span>' +
|
||||
'</div>' +
|
||||
@@ -218,6 +235,7 @@
|
||||
document.getElementById('email-refresh-btn').addEventListener('click', function() {
|
||||
loadMessageList();
|
||||
});
|
||||
document.getElementById('email-empty-folder-btn').addEventListener('click', emptyCurrentFolder);
|
||||
|
||||
// Matches sender, subject, or body content in whatever folder is
|
||||
// currently open (see __imap.cpp's searchMessages()) - an empty
|
||||
@@ -444,6 +462,38 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Permanently deletes every message in the CURRENT folder (only ever
|
||||
// reachable while viewing Spam or Trash - see syncActiveFolder()'s own
|
||||
// button-visibility gate, and email.jet's independent server-side
|
||||
// allowlist, which is the real enforcement). Unlike trashMessage()
|
||||
// there's no undo, no "move somewhere" - a real, human-readable confirm()
|
||||
// is the whole safety net here, matching how Gmail/Outlook both gate
|
||||
// "Empty Trash now" behind exactly one extra click and nothing fancier.
|
||||
function emptyCurrentFolder() {
|
||||
if (currentFolder !== 'Spam' && currentFolder !== 'Trash')
|
||||
return;
|
||||
if (!window.confirm('Permanently delete every message in ' + currentFolder + '? This cannot be undone.'))
|
||||
return;
|
||||
var btn = document.getElementById('email-empty-folder-btn');
|
||||
if (btn) btn.disabled = true;
|
||||
post('/email/emptyfolder', { folder: currentFolder })
|
||||
.then(function(res) {
|
||||
if (btn) btn.disabled = false;
|
||||
if (!res.ok) {
|
||||
window.alert(res.error || 'Could not empty the folder.');
|
||||
return;
|
||||
}
|
||||
currentUid = null;
|
||||
document.getElementById('email-reading-pane').innerHTML =
|
||||
'<div id="email-empty-state">Select a message to read it.</div>';
|
||||
loadMessageList();
|
||||
})
|
||||
.catch(function() {
|
||||
if (btn) btn.disabled = false;
|
||||
window.alert('Empty-folder request failed.');
|
||||
});
|
||||
}
|
||||
|
||||
// Same fade-out/fetch-concurrently/fade-in shape as openMessage() and
|
||||
// spa.js's own navigate() - every list refresh (folder switch,
|
||||
// refresh button) gets the same smooth transition instead of a flash
|
||||
@@ -488,8 +538,10 @@
|
||||
if (!skipFade)
|
||||
list.classList.remove('email-fading');
|
||||
})
|
||||
.catch(function() {
|
||||
list.innerHTML = '<div id="email-empty-state">Could not load messages.</div>';
|
||||
.catch(function(err) {
|
||||
console.error('loadMessageList failed:', err);
|
||||
list.innerHTML = '<div id="email-empty-state">Could not load messages' +
|
||||
(err && err.message ? ': ' + escapeHtml(err.message) : '.') + '</div>';
|
||||
if (!skipFade)
|
||||
list.classList.remove('email-fading');
|
||||
});
|
||||
@@ -506,8 +558,10 @@
|
||||
// cosmetic problem, not worth surfacing as a user-visible failure.
|
||||
function loadFolderCounts() {
|
||||
post('/email/folders', {}).then(function(res) {
|
||||
if (res.error)
|
||||
if (res.error) {
|
||||
console.error('loadFolderCounts server error:', res.error);
|
||||
return;
|
||||
}
|
||||
var folders = ['Inbox', 'Spam', 'Trash'];
|
||||
for (var i = 0; i < folders.length; i++) {
|
||||
var f = folders[i];
|
||||
@@ -515,7 +569,9 @@
|
||||
if (span && res[f])
|
||||
span.textContent = res[f].messages > 0 ? (res[f].unseen + '/' + res[f].messages) : '';
|
||||
}
|
||||
}).catch(function() {});
|
||||
}).catch(function(err) {
|
||||
console.error('loadFolderCounts failed:', err);
|
||||
});
|
||||
}
|
||||
|
||||
function loadAccounts() {
|
||||
@@ -756,8 +812,10 @@
|
||||
}
|
||||
pane.classList.remove('email-fading');
|
||||
})
|
||||
.catch(function() {
|
||||
pane.innerHTML = '<div id="email-empty-state">Could not load message.</div>';
|
||||
.catch(function(err) {
|
||||
console.error('openMessage failed:', err);
|
||||
pane.innerHTML = '<div id="email-empty-state">Could not load message' +
|
||||
(err && err.message ? ': ' + escapeHtml(err.message) : '.') + '</div>';
|
||||
pane.classList.remove('email-fading');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
|
||||
@font-face {
|
||||
font-family: avenir;
|
||||
src: url('https://barant.com/fonts/AvenirLTStd-Light.ttf');
|
||||
src: url('https://barant.com/assets/AvenirLTStd-Light.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: source;
|
||||
src: url('https://barant.com/fonts/jackinput.TTF');
|
||||
src: url('https://barant.com/assets/jackinput.TTF');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: exo2;
|
||||
src: url('https://barant.com/fonts/Exo2-RegularCondensed.otf');
|
||||
src: url('https://barant.com/assets/Exo2-RegularCondensed.otf');
|
||||
}
|
||||
|
||||
:root {
|
||||
@@ -283,7 +283,7 @@ textarea.fieldinputerror {
|
||||
background: linear-gradient(180deg, #131318, #0d0d10);
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
border-bottom: 1px solid var(--bond-line);
|
||||
max-height: 80px;
|
||||
max-height: 125px;
|
||||
}
|
||||
.entryform {
|
||||
background: #232330;
|
||||
@@ -365,24 +365,43 @@ textarea.fieldinputerror {
|
||||
transition: color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
/* The currently-active entry in a page's own sidebar submenu (e.g.
|
||||
opensource.menu's list of subpages) - a background highlight rather
|
||||
than baritemselected's "raised tab" treatment, since these are plain
|
||||
inline links stacked in a list, not tabs sitting on a bar edge.
|
||||
Applied server-side (see opensource.menu) by comparing each
|
||||
linkbutton's own subpage against $[SUBPAGE] - spa.js already
|
||||
re-renders and swaps this menu's markup on every client-side
|
||||
navigation (see its #_spa_panelmenu handling), so this stays correct
|
||||
without any script of its own. */
|
||||
/* Every entry in a page's own sidebar submenu (e.g. opensource.menu's
|
||||
list of subpages) shares this same box model - selected and
|
||||
unselected alike - so the only thing that changes when an item
|
||||
becomes active is its background/border, never its box size or the
|
||||
position of its own text. Giving only the active item padding/margin
|
||||
(the original approach) made its text visibly shift the moment it
|
||||
was selected, since the unselected items sat flush with none. */
|
||||
#panelmenu a {
|
||||
display: block;
|
||||
padding: 2px 6px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
/* The currently-active entry - a background highlight rather than
|
||||
baritemselected's "raised tab" treatment, since these are plain
|
||||
links stacked in a list, not tabs sitting on a bar edge. Applied
|
||||
server-side (see opensource.menu) by comparing each linkbutton's own
|
||||
subpage against $[SUBPAGE] - spa.js also applies it instantly client-
|
||||
side on click (see its #panelmenu click listener) and then
|
||||
re-confirms it from the server's own #_spa_panelmenu markup once the
|
||||
fetch resolves, so this stays correct either way. */
|
||||
.submenuitem-active {
|
||||
background: var(--bond-panel-2);
|
||||
color: var(--bond-gold-bright) !important;
|
||||
padding: 2px 6px;
|
||||
margin: -2px -6px;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 0 0 1px var(--bond-gold);
|
||||
}
|
||||
|
||||
/* Every menu entry's own markup is <linkbutton...></linkbutton><br> - that
|
||||
<br> was needed to force a line break after an inline link, but every
|
||||
entry is display:block now (its own implicit line break), so the
|
||||
trailing <br> doubles up into a blank line for every item, not just
|
||||
the active one. */
|
||||
#panelmenu a + br {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: var(--bond-panel);
|
||||
margin: 10px;
|
||||
@@ -861,3 +880,499 @@ textarea.fieldinputerror {
|
||||
.filemgr-progress-fill { height: 100%; width: 0%; background: var(--bond-gold-bright); transition: width 0.15s ease; }
|
||||
.filemgr-item.filemgr-done .filemgr-progress-fill { background: #6c6; }
|
||||
.filemgr-item.filemgr-failed .filemgr-progress-fill { background: #c66; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Fades in during an SPA navigation fetch - lives outside #content (a
|
||||
content.innerHTML swap would just wipe it out otherwise), positioned
|
||||
relative to the viewport rather than the resizable content column so
|
||||
dragging #panelmenu-resizer narrower/wider never throws its centering
|
||||
off. The transition duration alone (no separate timer) is what keeps
|
||||
a fast load from ever showing it at a noticeable opacity before the
|
||||
class comes back off. */
|
||||
.spa-loading-indicator {
|
||||
position: fixed;
|
||||
top: 90px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: var(--bond-text-dim);
|
||||
font-size: 10pt;
|
||||
letter-spacing: 1px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.6s ease;
|
||||
pointer-events: none;
|
||||
z-index: 500;
|
||||
}
|
||||
.spa-loading-indicator.spa-loading-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
/* Fades in during an SPA navigation fetch - lives outside #content (a
|
||||
content.innerHTML swap would just wipe it out otherwise), positioned
|
||||
relative to the viewport rather than the resizable content column so
|
||||
dragging #panelmenu-resizer narrower/wider never throws its centering
|
||||
off. The transition duration alone (no separate timer) is what keeps
|
||||
a fast load from ever showing it at a noticeable opacity before the
|
||||
class comes back off. */
|
||||
.spa-loading-indicator {
|
||||
position: fixed;
|
||||
top: 90px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: var(--bond-text-dim);
|
||||
font-size: 10pt;
|
||||
letter-spacing: 1px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.6s ease;
|
||||
pointer-events: none;
|
||||
z-index: 500;
|
||||
}
|
||||
.spa-loading-indicator.spa-loading-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
/* Keeps the music/library/ianslibrary subpages pinned to the browser
|
||||
window's height (footer always visible, no whole-page scroll) while
|
||||
the song list itself scrolls internally - the exact same pattern
|
||||
already proven for the email app's own message list
|
||||
(.pageclass:has(#email-app)), just scoped to this marker instead and
|
||||
adapted for <sectionframe>'s own heading-then-contents structure
|
||||
(the heading needs to stay a fixed size above the scrolling list,
|
||||
not get swept into the same scroll region). height:100% has to be
|
||||
set explicitly at every level down to .music-song-list itself -
|
||||
percentage heights only resolve against an ancestor with its own
|
||||
definite height, and a plain block element's default is auto, which
|
||||
does not count, so skipping any one level here would silently break
|
||||
the whole chain. #main-subpage (main.page's generic per-subpage
|
||||
wrapper, between #content and .sectionframe) is exactly that kind of
|
||||
skip - missing it let .sectionframe's height:100% resolve to auto,
|
||||
so .music-song-list sized itself to its full content height instead
|
||||
of a scrollable box, and the overflow got clipped by .pageclass's
|
||||
own overflow:hidden with no scrollbar to show for it. */
|
||||
.pageclass:has(.music-song-list) {
|
||||
height: calc(100vh - 150px);
|
||||
overflow: hidden;
|
||||
}
|
||||
#content:has(.music-song-list) {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#main-subpage:has(.music-song-list) {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sectionframe:has(.music-song-list) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sectionframe:has(.music-song-list) .sectionframecontents {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.music-song-list {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Fades in during an SPA navigation fetch - lives outside #content (a
|
||||
content.innerHTML swap would just wipe it out otherwise), positioned
|
||||
relative to the viewport rather than the resizable content column so
|
||||
dragging #panelmenu-resizer narrower/wider never throws its centering
|
||||
off. The transition duration alone (no separate timer) is what keeps
|
||||
a fast load from ever showing it at a noticeable opacity before the
|
||||
class comes back off. */
|
||||
.spa-loading-indicator {
|
||||
position: fixed;
|
||||
top: 90px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: var(--bond-text-dim);
|
||||
font-size: 10pt;
|
||||
letter-spacing: 1px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.6s ease;
|
||||
pointer-events: none;
|
||||
z-index: 500;
|
||||
}
|
||||
.spa-loading-indicator.spa-loading-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Global persistent music player band - slides open only while playing */
|
||||
.globalplayer-band {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
background: var(--bond-panel);
|
||||
border-bottom: 1pt solid var(--bond-line);
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
transition: max-height 0.3s ease, padding 0.3s ease;
|
||||
}
|
||||
.globalplayer-band.globalplayer-open {
|
||||
max-height: 54px;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
.globalplayer-title {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
/* A flex item's default min-width is its content's own min-content
|
||||
size, not 0 - without this, a long song name would force the whole
|
||||
LCD panel wider (squeezing the volume slider/buttons) rather than
|
||||
actually truncating against the space it is given. */
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
background: #000;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
padding: 4px 10px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: inset 0 0 8px rgba(26,143,196,0.12), inset 0 2px 4px rgba(0,0,0,0.8);
|
||||
}
|
||||
.globalplayer-duration {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 8px;
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
font-size: 10pt;
|
||||
color: #1a8fc4;
|
||||
text-shadow: 0 0 4px rgba(26,143,196,0.7);
|
||||
opacity: 0.85;
|
||||
}
|
||||
.globalplayer-random-indicator {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 8px;
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
font-size: 7pt;
|
||||
letter-spacing: 1px;
|
||||
color: #1a8fc4;
|
||||
text-shadow: 0 0 4px rgba(26,143,196,0.7);
|
||||
opacity: 0.85;
|
||||
display: none;
|
||||
}
|
||||
.globalplayer-random-indicator.globalplayer-random-indicator-visible {
|
||||
display: block;
|
||||
}
|
||||
.globalplayer-title-text {
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
font-size: 20pt;
|
||||
line-height: 1.1;
|
||||
color: #1a8fc4;
|
||||
text-shadow: 0 0 5px rgba(26,143,196,0.8), 0 0 1px rgba(26,143,196,0.9);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.globalplayer-progress {
|
||||
position: relative;
|
||||
height: 8px;
|
||||
width: 100%;
|
||||
background: rgba(26,143,196,0.15);
|
||||
border-radius: 4px;
|
||||
margin-top: 4px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
touch-action: none;
|
||||
}
|
||||
.globalplayer-progress-fill {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
background: #1a8fc4;
|
||||
border-radius: 4px 0 0 4px;
|
||||
box-shadow: 0 0 4px rgba(26,143,196,0.8);
|
||||
transition: width 0.2s linear;
|
||||
pointer-events: none;
|
||||
}
|
||||
.globalplayer-progress-handle {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 30%, #fff6d0 0%, #d4af37 55%, #6b5313 100%);
|
||||
border: 1px solid #5a4410;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.7);
|
||||
transform: translate(-50%, -50%);
|
||||
transition: left 0.2s linear;
|
||||
pointer-events: none;
|
||||
}
|
||||
.globalplayer-progress.globalplayer-progress-dragging .globalplayer-progress-fill,
|
||||
.globalplayer-progress.globalplayer-progress-dragging .globalplayer-progress-handle {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/* Square, touch-tone-style buttons for the player band - same dished
|
||||
gold-on-black look as the sipphone tag's dialpad keys. */
|
||||
.globalplayer-btn {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
background: radial-gradient(circle at 50% 50%, #8a6a22 0%, #b8903a 32%, #d4af37 55%, #ecce79 80%, #fff6d0 100%);
|
||||
border: 1px solid #5a4410;
|
||||
box-shadow:
|
||||
0 2px 0 #4a3a0f,
|
||||
0 3px 5px rgba(0,0,0,0.5),
|
||||
inset 0 3px 5px rgba(0,0,0,0.45),
|
||||
inset 0 -1px 1px rgba(255,255,255,0.5);
|
||||
color: #3a2d05;
|
||||
cursor: pointer;
|
||||
transition: transform 0.06s ease, box-shadow 0.06s ease;
|
||||
}
|
||||
.globalplayer-btn svg { width: 16px; height: 16px; }
|
||||
.globalplayer-btn:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow:
|
||||
inset 0 4px 8px rgba(0,0,0,0.6),
|
||||
inset 0 -1px 1px rgba(255,255,255,0.3);
|
||||
}
|
||||
.globalplayer-btn-text {
|
||||
width: auto;
|
||||
padding: 0 12px;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Stereo FFT-style bar graph - left channel above the midline, right
|
||||
channel below it, drawn directly onto a small canvas. */
|
||||
.globalplayer-eq {
|
||||
flex-shrink: 0;
|
||||
width: 60px;
|
||||
height: 32px;
|
||||
background: #000;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Playlist dropdown - its own independent sliding strip directly below
|
||||
the player band, NOT nested inside it: the band's own overflow:hidden
|
||||
(needed for its slide animation) would otherwise clip anything
|
||||
positioned to pop out below it, which is why this was invisible
|
||||
before despite the open/close class toggling correctly in JS. */
|
||||
.globalplayer-queue {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
background: var(--bond-panel-2);
|
||||
border-bottom: 1pt solid var(--bond-line);
|
||||
transition: max-height 0.25s ease;
|
||||
}
|
||||
.globalplayer-queue.globalplayer-queue-open {
|
||||
max-height: 240px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.globalplayer-queue-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin: 6px 10px;
|
||||
padding: 8px 14px;
|
||||
border: 1px solid var(--bond-line);
|
||||
border-radius: 8px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
color: var(--bond-text-dim);
|
||||
}
|
||||
.globalplayer-queue-name {
|
||||
font-size: 18pt;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.globalplayer-queue-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.globalplayer-queue-handle {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--bond-text-dim);
|
||||
cursor: grab;
|
||||
}
|
||||
.globalplayer-queue-handle svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
.globalplayer-queue-item.globalplayer-queue-dragging {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.globalplayer-queue-item.globalplayer-queue-dragover {
|
||||
border-top: 2px solid var(--bond-gold-bright);
|
||||
}
|
||||
.globalplayer-queue-right {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.globalplayer-queue-duration {
|
||||
flex-shrink: 0;
|
||||
font-size: 9pt;
|
||||
opacity: 0.75;
|
||||
}
|
||||
.globalplayer-queue-remove {
|
||||
flex-shrink: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--bond-line);
|
||||
background: linear-gradient(180deg, #1c1c24, #131318);
|
||||
color: var(--bond-text-dim);
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
.globalplayer-queue-remove svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: block;
|
||||
}
|
||||
.globalplayer-queue-remove:hover {
|
||||
border-color: var(--bond-red);
|
||||
color: var(--bond-red);
|
||||
box-shadow: 0 0 0.5em rgba(161,58,58,0.35);
|
||||
background: linear-gradient(180deg, #24242e, #1a1a20);
|
||||
}
|
||||
.globalplayer-queue-item.globalplayer-queue-current {
|
||||
color: var(--bond-gold-bright);
|
||||
font-weight: 600;
|
||||
border-color: var(--bond-gold);
|
||||
background: rgba(212,175,55,0.08);
|
||||
}
|
||||
|
||||
/* Tactile feedback for clicking a song to queue it: an immediate flash
|
||||
on the row, plus a lasting checkmark so it is clear at a glance which
|
||||
songs are already in the queue. */
|
||||
/* Scoped to the name span, not the row itself: the row is a flex
|
||||
container with justify-content:space-between, and a ::before on it
|
||||
directly becomes its own flex item - with 3 items instead of 2, the
|
||||
name ends up looking centered between the checkmark and the duration/
|
||||
remove group instead of staying left-aligned. Putting it on the name
|
||||
span keeps it as ordinary inline content inside that one flex item. */
|
||||
.song-queued .music-song-name::before {
|
||||
content: "\2713 ";
|
||||
color: var(--bond-gold-bright);
|
||||
}
|
||||
.song-queued-flash {
|
||||
animation: songQueuedFlash 0.6s ease;
|
||||
}
|
||||
@keyframes songQueuedFlash {
|
||||
0% { background: var(--bond-gold-bright); color: var(--bond-bg); }
|
||||
100% { background: transparent; }
|
||||
}
|
||||
|
||||
/* Song-picker rows (music/jukebox subpages) - same boxed, rounded-corner
|
||||
look as the playlist dropdown's own entries, for visual consistency
|
||||
between "songs you can pick" and "what's in the queue". */
|
||||
.music-song-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin: 4px 0;
|
||||
padding: 5px 10px;
|
||||
border: 1px solid var(--bond-line);
|
||||
border-radius: 8px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
color: var(--bond-text-dim);
|
||||
cursor: pointer;
|
||||
}
|
||||
.music-song-row:hover {
|
||||
border-color: var(--bond-gold);
|
||||
background: rgba(255,255,255,0.06);
|
||||
}
|
||||
.music-song-name {
|
||||
font-size: 12pt;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.music-song-duration {
|
||||
flex-shrink: 0;
|
||||
font-size: 8pt;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* Volume slider - a small gold knob riding a thin gold-tinted track */
|
||||
.globalplayer-volume {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
flex-shrink: 0;
|
||||
width: 70px;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
background: var(--bond-line);
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.globalplayer-volume::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 30%, #fff6d0 0%, #d4af37 55%, #6b5313 100%);
|
||||
border: 1px solid #5a4410;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.6);
|
||||
cursor: pointer;
|
||||
}
|
||||
.globalplayer-volume::-moz-range-track {
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
background: var(--bond-line);
|
||||
}
|
||||
.globalplayer-volume::-moz-range-thumb {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 30%, #fff6d0 0%, #d4af37 55%, #6b5313 100%);
|
||||
border: 1px solid #5a4410;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.6);
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
(function() {
|
||||
var content = document.getElementById('content');
|
||||
var form = document.getElementById('mainform');
|
||||
var loadingIndicator = document.getElementById('spa-loading-indicator');
|
||||
// Lives outside #content (a sibling in the persistent shell, next to
|
||||
// the menu bar/form) - a fragment swap never touches it on its own,
|
||||
// so a per-page side menu would otherwise stay frozen on whichever
|
||||
@@ -220,6 +221,12 @@
|
||||
function navigate(url, push) {
|
||||
var sep = url.indexOf('?') === -1 ? '?' : '&';
|
||||
content.classList.add('spa-fading');
|
||||
// Opacity transition alone (see the CSS) means a fetch that resolves
|
||||
// quickly never gets the indicator past a barely-visible opacity
|
||||
// before this removes the class again - exactly the "do not flash
|
||||
// this for a fast load" behavior wanted, with no separate delay
|
||||
// timer needed to achieve it.
|
||||
if (loadingIndicator) loadingIndicator.classList.add('spa-loading-visible');
|
||||
Promise.all([
|
||||
fetch(url + sep + '_fragment=1', { credentials: 'same-origin' }).then(function(r) { return r.text(); }),
|
||||
delay(180)
|
||||
@@ -233,6 +240,7 @@
|
||||
syncActiveTab(finalUrl.split('?')[0]);
|
||||
}
|
||||
content.classList.remove('spa-fading');
|
||||
if (loadingIndicator) loadingIndicator.classList.remove('spa-loading-visible');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -254,6 +262,7 @@
|
||||
var subpage = fd.get('SUBPAGE') || '';
|
||||
var url = formPrefix + '/' + page + (subpage ? '/' + subpage : '');
|
||||
content.classList.add('spa-fading');
|
||||
if (loadingIndicator) loadingIndicator.classList.add('spa-loading-visible');
|
||||
Promise.all([
|
||||
fetch(url + '?_fragment=1', {
|
||||
method: 'POST',
|
||||
@@ -271,6 +280,7 @@
|
||||
syncActiveTab(finalUrl.split('?')[0]);
|
||||
}
|
||||
content.classList.remove('spa-fading');
|
||||
if (loadingIndicator) loadingIndicator.classList.remove('spa-loading-visible');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -279,6 +289,24 @@
|
||||
navigate(window.location.pathname + window.location.search, false);
|
||||
});
|
||||
|
||||
// Instant visual feedback on a side-menu click - without this, the
|
||||
// active-item highlight only updated once applyResponse() swapped in
|
||||
// the new #_spa_panelmenu markup after the fetch finished, which read
|
||||
// as unresponsive (the click did nothing visible until the whole
|
||||
// subpage had already loaded). That server-rendered swap is still the
|
||||
// authoritative source of truth and will correct this on arrival (e.g.
|
||||
// if a click ends up redirected somewhere else entirely), so this is
|
||||
// purely an optimistic bridge, not a second source of truth.
|
||||
if (panelMenu) {
|
||||
panelMenu.addEventListener('click', function(e) {
|
||||
var a = e.target.closest('a');
|
||||
if (!a || !panelMenu.contains(a)) return;
|
||||
var current = panelMenu.querySelector('.submenuitem-active');
|
||||
if (current) current.classList.remove('submenuitem-active');
|
||||
a.classList.add('submenuitem-active');
|
||||
});
|
||||
}
|
||||
|
||||
// Drag-to-resize for the side menu (#panelmenu) against the main
|
||||
// content column - the resizer bar (#panelmenu-resizer) lives in the
|
||||
// persistent shell right alongside panelMenu itself (see its own
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
<tag name="sipphone">
|
||||
|
||||
<style>
|
||||
.sipphone-bond {
|
||||
width: 360px;
|
||||
margin: 10px 0 24px 0;
|
||||
padding: 14px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(160deg, #1a1a1a 0%, #060606 60%, #000 100%);
|
||||
border: 1px solid #000;
|
||||
box-shadow:
|
||||
0 0 0 2px #2a2a2a,
|
||||
0 0 0 3px #b8860b,
|
||||
0 10px 30px rgba(0,0,0,0.6),
|
||||
inset 0 1px 0 rgba(255,255,255,0.05);
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
color: #d4af37;
|
||||
}
|
||||
.sipphone-bond .sipphone-brand {
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
letter-spacing: 4px;
|
||||
color: #d4af37;
|
||||
text-shadow: 0 0 6px rgba(212,175,55,0.6);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.sipphone-bond .sipphone-lcd {
|
||||
background: #000;
|
||||
border: 2px solid #333;
|
||||
border-radius: 4px;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 10px;
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
color: #39ff6a;
|
||||
text-shadow: 0 0 5px rgba(57,255,106,0.8), 0 0 1px rgba(57,255,106,0.9);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
min-height: 56px;
|
||||
box-shadow: inset 0 0 12px rgba(57,255,106,0.15), inset 0 2px 6px rgba(0,0,0,0.8);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sipphone-bond .sipphone-lcd::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: repeating-linear-gradient(
|
||||
to bottom,
|
||||
rgba(0,0,0,0.15) 0px,
|
||||
rgba(0,0,0,0.15) 1px,
|
||||
transparent 1px,
|
||||
transparent 3px
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
.sipphone-bond .sipphone-lcd-line1 { font-size: 30px; font-weight: bold; line-height: 1.2; }
|
||||
.sipphone-bond .sipphone-lcd-line2 { opacity: 0.85; }
|
||||
.sipphone-bond .sipphone-video-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
background: #000;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
}
|
||||
.sipphone-bond .sipphone-video-wrap.active { display: block; }
|
||||
.sipphone-bond .sipphone-remote-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
background: #000;
|
||||
}
|
||||
.sipphone-bond .sipphone-local-video {
|
||||
position: absolute;
|
||||
width: 72px;
|
||||
height: 54px;
|
||||
right: 6px;
|
||||
bottom: 6px;
|
||||
border: 1px solid #d4af37;
|
||||
border-radius: 3px;
|
||||
object-fit: cover;
|
||||
background: #111;
|
||||
}
|
||||
.sipphone-bond .sipphone-dialpad {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 44px);
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.sipphone-bond .sipphone-key {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #3a2d05;
|
||||
background: radial-gradient(circle at 50% 50%, #8a6a22 0%, #b8903a 32%, #d4af37 55%, #ecce79 80%, #fff6d0 100%);
|
||||
border: 1px solid #5a4410;
|
||||
box-shadow:
|
||||
0 2px 0 #4a3a0f,
|
||||
0 4px 6px rgba(0,0,0,0.6),
|
||||
inset 0 3px 5px rgba(0,0,0,0.45),
|
||||
inset 0 -1px 1px rgba(255,255,255,0.5);
|
||||
transition: transform 0.06s ease, box-shadow 0.06s ease;
|
||||
}
|
||||
.sipphone-bond .sipphone-key:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow:
|
||||
inset 0 4px 8px rgba(0,0,0,0.6),
|
||||
inset 0 -1px 1px rgba(255,255,255,0.3);
|
||||
}
|
||||
.sipphone-bond .sipphone-controls {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
.sipphone-bond .sipphone-btn {
|
||||
flex: 1;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
padding: 9px 0;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
color: #3a2d05;
|
||||
background: linear-gradient(180deg, #f3d77a 0%, #d4af37 45%, #9c7a1f 100%);
|
||||
border: 1px solid #5a4410;
|
||||
box-shadow: 0 2px 0 #4a3a0f, 0 4px 8px rgba(0,0,0,0.6), inset 0 1px 1px rgba(255,255,255,0.7);
|
||||
}
|
||||
.sipphone-bond .sipphone-btn.sipphone-hangup {
|
||||
background: linear-gradient(180deg, #e06666 0%, #a30000 60%, #6b0000 100%);
|
||||
color: #2a0000;
|
||||
border-color: #3a0000;
|
||||
}
|
||||
.sipphone-bond .sipphone-btn:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow: inset 0 1px 3px rgba(0,0,0,0.5);
|
||||
}
|
||||
.sipphone-bond .sipphone-btn.sipphone-btn-disabled {
|
||||
cursor: default;
|
||||
opacity: 0.35;
|
||||
filter: grayscale(70%);
|
||||
box-shadow: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
.sipphone-bond .sipphone-lcd-status-offline {
|
||||
color: #ff3b3b;
|
||||
text-shadow: 0 0 6px rgba(255,59,59,0.8);
|
||||
}
|
||||
.sipphone-bond .sipphone-status-dot {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
margin-right: 6px;
|
||||
background: #666;
|
||||
box-shadow: 0 0 4px #666;
|
||||
}
|
||||
.sipphone-bond .sipphone-status-dot.reg {
|
||||
background: #39ff6a;
|
||||
box-shadow: 0 0 6px #39ff6a;
|
||||
}
|
||||
.sipphone-bond .sipphone-status-dot.incall {
|
||||
background: #ffcc00;
|
||||
box-shadow: 0 0 6px #ffcc00;
|
||||
}
|
||||
</style>
|
||||
|
||||
<sql>select id, exten, secret from phones.extensions where user_id=$[_login_id] and secret is not null</sql>
|
||||
<ifrow>
|
||||
<whilerow>
|
||||
<div class="sipphone-bond" id="sipphone-$[.id]"
|
||||
data-sipphone-id="$[.id]"
|
||||
data-sipphone-exten="$[.exten]"
|
||||
data-sipphone-secret="$[.secret]"
|
||||
data-sipphone-domain="barant.com"
|
||||
data-sipphone-wss="wss://barant.com:8089/ws">
|
||||
|
||||
<div class="sipphone-brand">◆ B · A · R · A · N · T ◆</div>
|
||||
|
||||
<div class="sipphone-lcd">
|
||||
<div class="sipphone-lcd-line1" data-role="lcd-line1">$[.exten]</div>
|
||||
<div class="sipphone-lcd-line2" data-role="lcd-line2"><span class="sipphone-status-dot" data-role="status-dot"></span><span data-role="lcd-status">OFFLINE</span></div>
|
||||
</div>
|
||||
|
||||
<div class="sipphone-video-wrap" data-role="video-wrap">
|
||||
<video class="sipphone-remote-video" data-role="remote-video" autoplay playsinline></video>
|
||||
<video class="sipphone-local-video" data-role="local-video" autoplay playsinline muted></video>
|
||||
</div>
|
||||
|
||||
<div class="sipphone-dialpad" data-role="dialpad">
|
||||
<div class="sipphone-key" data-digit="1">1</div>
|
||||
<div class="sipphone-key" data-digit="2">2</div>
|
||||
<div class="sipphone-key" data-digit="3">3</div>
|
||||
<div class="sipphone-key" data-digit="4">4</div>
|
||||
<div class="sipphone-key" data-digit="5">5</div>
|
||||
<div class="sipphone-key" data-digit="6">6</div>
|
||||
<div class="sipphone-key" data-digit="7">7</div>
|
||||
<div class="sipphone-key" data-digit="8">8</div>
|
||||
<div class="sipphone-key" data-digit="9">9</div>
|
||||
<div class="sipphone-key" data-digit="*">*</div>
|
||||
<div class="sipphone-key" data-digit="0">0</div>
|
||||
<div class="sipphone-key" data-digit="#">#</div>
|
||||
</div>
|
||||
|
||||
<div class="sipphone-controls">
|
||||
<div class="sipphone-btn" data-role="call-hangup-btn">CALL</div>
|
||||
<div class="sipphone-btn" data-role="video-toggle-btn">VIDEO: OFF</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</whilerow>
|
||||
|
||||
<script type="module">
|
||||
import * as SIP from "https://cdn.jsdelivr.net/npm/sip.js@0.21.2/lib/index.min.js";
|
||||
(function() {
|
||||
function initSipPhone(root) {
|
||||
var exten = root.dataset.sipphoneExten;
|
||||
var secret = root.dataset.sipphoneSecret;
|
||||
var domain = root.dataset.sipphoneDomain;
|
||||
var wss = root.dataset.sipphoneWss;
|
||||
|
||||
var dialedDigits = "";
|
||||
var currentSession = null;
|
||||
var videoEnabled = false;
|
||||
var isRegistered = false;
|
||||
var previewStream = null;
|
||||
|
||||
var lcdLine1 = root.querySelector('[data-role="lcd-line1"]');
|
||||
var lcdStatus = root.querySelector('[data-role="lcd-status"]');
|
||||
var statusDot = root.querySelector('[data-role="status-dot"]');
|
||||
var videoWrap = root.querySelector('[data-role="video-wrap"]');
|
||||
var remoteVideo = root.querySelector('[data-role="remote-video"]');
|
||||
var localVideo = root.querySelector('[data-role="local-video"]');
|
||||
var callHangupBtn = root.querySelector('[data-role="call-hangup-btn"]');
|
||||
var videoToggleBtn = root.querySelector('[data-role="video-toggle-btn"]');
|
||||
|
||||
function setLcd(line1, status, dotClass) {
|
||||
if (line1 !== undefined) lcdLine1.textContent = line1;
|
||||
if (status !== undefined) lcdStatus.textContent = status;
|
||||
statusDot.className = "sipphone-status-dot" + (dotClass ? (" " + dotClass) : "");
|
||||
}
|
||||
|
||||
function updateCallButton() {
|
||||
if (currentSession) {
|
||||
callHangupBtn.textContent = "END";
|
||||
callHangupBtn.classList.add("sipphone-hangup");
|
||||
callHangupBtn.classList.remove("sipphone-btn-disabled");
|
||||
} else {
|
||||
callHangupBtn.textContent = "CALL";
|
||||
callHangupBtn.classList.remove("sipphone-hangup");
|
||||
callHangupBtn.classList.toggle("sipphone-btn-disabled", !isRegistered || !dialedDigits);
|
||||
}
|
||||
lcdStatus.classList.toggle("sipphone-lcd-status-offline", !isRegistered);
|
||||
}
|
||||
|
||||
var ua = new SIP.UserAgent({
|
||||
uri: SIP.UserAgent.makeURI("sip:" + exten + "@" + domain),
|
||||
transportOptions: { server: wss },
|
||||
authorizationUsername: exten,
|
||||
authorizationPassword: secret,
|
||||
logLevel: "error",
|
||||
delegate: {
|
||||
onInvite: function(invitation) {
|
||||
currentSession = invitation;
|
||||
updateCallButton();
|
||||
setLcd("INCOMING CALL", "RINGING", "incall");
|
||||
attachSessionHandlers(invitation);
|
||||
invitation.accept({
|
||||
sessionDescriptionHandlerOptions: {
|
||||
constraints: { audio: true, video: videoEnabled }
|
||||
}
|
||||
}).then(function() {
|
||||
setLcd(exten, "IN CALL", "incall");
|
||||
videoWrap.classList.add("active");
|
||||
attachMedia(invitation);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var registerer = new SIP.Registerer(ua);
|
||||
|
||||
updateCallButton();
|
||||
|
||||
ua.start().then(function() {
|
||||
return registerer.register();
|
||||
}).then(function() {
|
||||
isRegistered = true;
|
||||
setLcd(exten, "READY", "reg");
|
||||
updateCallButton();
|
||||
}).catch(function() {
|
||||
isRegistered = false;
|
||||
setLcd(exten, "REG FAILED", "");
|
||||
updateCallButton();
|
||||
});
|
||||
|
||||
function stopPreview() {
|
||||
if (previewStream) {
|
||||
previewStream.getTracks().forEach(function(t) { t.stop(); });
|
||||
previewStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
function startPreview() {
|
||||
if (previewStream || currentSession) return;
|
||||
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
|
||||
if (!videoEnabled || currentSession) {
|
||||
stream.getTracks().forEach(function(t) { t.stop(); });
|
||||
return;
|
||||
}
|
||||
previewStream = stream;
|
||||
localVideo.srcObject = stream;
|
||||
videoWrap.classList.add("active");
|
||||
}).catch(function() {
|
||||
videoEnabled = false;
|
||||
videoToggleBtn.textContent = "VIDEO: OFF";
|
||||
});
|
||||
}
|
||||
|
||||
function attachMedia(session) {
|
||||
stopPreview();
|
||||
var pc = session.sessionDescriptionHandler.peerConnection;
|
||||
var remoteStream = new MediaStream();
|
||||
pc.getReceivers().forEach(function(receiver) {
|
||||
if (receiver.track) remoteStream.addTrack(receiver.track);
|
||||
});
|
||||
remoteVideo.srcObject = remoteStream;
|
||||
|
||||
var localStream = new MediaStream();
|
||||
pc.getSenders().forEach(function(sender) {
|
||||
if (sender.track) localStream.addTrack(sender.track);
|
||||
});
|
||||
localVideo.srcObject = localStream;
|
||||
}
|
||||
|
||||
function attachSessionHandlers(session) {
|
||||
session.stateChange.addListener(function(state) {
|
||||
if (state === SIP.SessionState.Established) {
|
||||
setLcd(undefined, "IN CALL", "incall");
|
||||
videoWrap.classList.add("active");
|
||||
attachMedia(session);
|
||||
} else if (state === SIP.SessionState.Terminated) {
|
||||
setLcd(exten, "READY", "reg");
|
||||
videoWrap.classList.remove("active");
|
||||
remoteVideo.srcObject = null;
|
||||
localVideo.srcObject = null;
|
||||
currentSession = null;
|
||||
dialedDigits = "";
|
||||
updateCallButton();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
root.querySelectorAll('[data-digit]').forEach(function(key) {
|
||||
key.addEventListener('click', function() {
|
||||
var d = key.dataset.digit;
|
||||
if (currentSession) {
|
||||
currentSession.sessionDescriptionHandler.sendDtmf(d);
|
||||
} else {
|
||||
dialedDigits += d;
|
||||
setLcd(dialedDigits || exten, dialedDigits ? "DIALING" : "READY", dialedDigits ? "" : "reg");
|
||||
updateCallButton();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
callHangupBtn.addEventListener('click', function() {
|
||||
if (!currentSession) {
|
||||
if (!dialedDigits || !isRegistered) return;
|
||||
var target = SIP.UserAgent.makeURI("sip:" + dialedDigits + "@" + domain);
|
||||
var inviter = new SIP.Inviter(ua, target, {
|
||||
sessionDescriptionHandlerOptions: {
|
||||
constraints: { audio: true, video: videoEnabled }
|
||||
}
|
||||
});
|
||||
currentSession = inviter;
|
||||
updateCallButton();
|
||||
attachSessionHandlers(inviter);
|
||||
setLcd(dialedDigits, "CALLING...", "incall");
|
||||
inviter.invite();
|
||||
} else {
|
||||
if (currentSession.state === SIP.SessionState.Established) {
|
||||
currentSession.bye();
|
||||
} else if (currentSession instanceof SIP.Inviter) {
|
||||
currentSession.cancel();
|
||||
} else {
|
||||
currentSession.reject();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
videoToggleBtn.addEventListener('click', function() {
|
||||
videoEnabled = !videoEnabled;
|
||||
videoToggleBtn.textContent = "VIDEO: " + (videoEnabled ? "ON" : "OFF");
|
||||
if (currentSession) return;
|
||||
if (videoEnabled) {
|
||||
startPreview();
|
||||
} else {
|
||||
stopPreview();
|
||||
localVideo.srcObject = null;
|
||||
videoWrap.classList.remove("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.sipphone-bond').forEach(initSipPhone);
|
||||
})();
|
||||
</script>
|
||||
</ifrow>
|
||||
|
||||
</tag>
|
||||
@@ -0,0 +1,83 @@
|
||||
<sectionframe title="Account Information">
|
||||
|
||||
<sql>select * from users where id=$[_login_id]</sql>
|
||||
<table>
|
||||
<tr><th class="left">Name:</th><td class="right">$[.name]</td></tr>
|
||||
<if value1="$[company_name]" value2="" type="ne">
|
||||
<tr><th class="left">Company Name:</th><td class="right">$[.company_name]</td></tr>
|
||||
</if>
|
||||
<tr><th class="left">E-Mail:</th><td class="right">$[.email]</td></tr>
|
||||
</table>
|
||||
|
||||
</sectionframe>
|
||||
|
||||
<sql>select * from user_messages where user_id=$[_login_id]</sql>$[sqlerror]
|
||||
<ifrow>
|
||||
<sectionframe title="Messages">
|
||||
<table>
|
||||
<whilerow>
|
||||
<tr>
|
||||
<td>$[.message]</td>
|
||||
<td>$[.link]</td>
|
||||
</tr>
|
||||
</whilerow>
|
||||
</table>
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
|
||||
<sql>select *
|
||||
from virtual_machines
|
||||
join products on virtual_machines.sku=products.sku
|
||||
where user_id=$[_login_id]</sql>
|
||||
<ifrow>
|
||||
<sectionframe title="Virtual Machines">
|
||||
|
||||
<whilerow>
|
||||
|
||||
<div style="margin-bottom: 3px; border: 1pt solid #000; border-radius: 5px;">
|
||||
<div style="float: left; padding: 2px 5px 0px 5px; vertical-align: middle; display: inline-block;"><img src="$[.image]" width="40"></div>
|
||||
<div style="float: left; background: #ccf; width: 300px; padding: 0px 0px 0px 0px;"><span style="font-size: 7pt;">Ubuntu Server 22.04 LTE</span>
|
||||
<br><span style="font-size: 9pt;"><b>barant.com</b></span>
|
||||
<br><span style="font-size: 7pt;">IP:</span> <span style="font-size: 9pt; font-family: monospace;">74.80.233.78</span></div>
|
||||
|
||||
<div style="float: right; padding: 5px;"><img src="/assets/power_on.png" width="32"></div>
|
||||
<div style="float: right; width: 90px; height: 48px; background: #444;"></div>
|
||||
<div style="float: right; margin-right: 25px;">3 days 2:10:33<br><br>34% of 40.2GB</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
|
||||
</whilerow>
|
||||
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
|
||||
<sql>select *
|
||||
from files
|
||||
join products on files.sku=products.sku
|
||||
where user_id=$[_login_id]</sql>
|
||||
<ifrow>
|
||||
<sectionframe title="Downloadable Content">
|
||||
<p>Content that has been purchased and can be downloaded is displayed
|
||||
below. Click on the Download button to begin downloading your files.</p>
|
||||
|
||||
<whilerow>
|
||||
<table style="margin: 3px;">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="$[.image]" width="50px"">
|
||||
</td>
|
||||
<td style="width: 300px; border: 1pt inset #888">
|
||||
$[.description]
|
||||
</td>
|
||||
<td style="width: 300px;">
|
||||
<div>$[license_name]</div><div>$[license_key]</div>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/downloadfile.cgi?sku=$[.sku]"><div class="button">Download</div></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</whilerow>
|
||||
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
@@ -0,0 +1,18 @@
|
||||
<sectionframe title="Invoices">
|
||||
<if value1="$[@_invoice_id]" value2="" type="ne">
|
||||
<sql>select user_id, status from invoices where id=$[@_invoice_id]</sql>
|
||||
<ifrow>
|
||||
<if expr="('$[.user_id]'='$[_login_id]') and ('$[.status]'='OPEN')">
|
||||
<div style="margin-bottom: 16px;">
|
||||
<include file="invoice.method">
|
||||
<include file="payment.method">
|
||||
</div>
|
||||
</if>
|
||||
</ifrow>
|
||||
</if>
|
||||
<div>
|
||||
<showtable process="selectinvoice" name="invoice_id" value="X">
|
||||
select id as X,id as 'Invoice ID',date_format(created, '%b %D %Y') as 'Date',amount as 'Amount',status as 'Status' from invoices where user_id=$[_login_id] order by created desc
|
||||
</showtable>
|
||||
</div>
|
||||
</sectionframe>
|
||||
@@ -0,0 +1,4 @@
|
||||
<include file="phones.section">
|
||||
|
||||
<include file="SIPPHONE.tag">
|
||||
<sipphone>
|
||||
@@ -0,0 +1,17 @@
|
||||
<sectionframe title="ACCOUNT">
|
||||
<if value1="$[SUBPAGE]" value2="" type="eq">
|
||||
<linkbutton page="account" class="submenuitem-active">ACCOUNT INFORMATION</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="account">ACCOUNT INFORMATION</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="phones" type="eq">
|
||||
<linkbutton page="account" subpage="phones" class="submenuitem-active">PHONES</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="account" subpage="phones">PHONES</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="invoices" type="eq">
|
||||
<linkbutton page="account" subpage="invoices" class="submenuitem-active">INVOICES</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="account" subpage="invoices">INVOICES</linkbutton><br>
|
||||
</if>
|
||||
</sectionframe>
|
||||
@@ -4,108 +4,16 @@
|
||||
<retain name="download_file">
|
||||
<retain name="invoice_id">
|
||||
|
||||
<sectionframe title="Account Information">
|
||||
|
||||
<sql>select * from users where id=$[_login_id]</sql>
|
||||
<table>
|
||||
<tr><th class="left">Name:</th><td class="right">$[.name]</td></tr>
|
||||
<if value1="$[company_name]" value2="" type="ne">
|
||||
<tr><th class="left">Company Name:</th><td class="right">$[.company_name]</td></tr>
|
||||
</if>
|
||||
<tr><th class="left">E-Mail:</th><td class="right">$[.email]</td></tr>
|
||||
</table>
|
||||
|
||||
</sectionframe>
|
||||
|
||||
<sql>select * from user_messages where user_id=$[_login_id]</sql>$[sqlerror]
|
||||
<ifrow>
|
||||
<sectionframe title="Messages">
|
||||
<table>
|
||||
<whilerow>
|
||||
<tr>
|
||||
<td>$[.message]</td>
|
||||
<td>$[.link]</td>
|
||||
</tr>
|
||||
</whilerow>
|
||||
</table>
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
|
||||
<sql>select *
|
||||
from virtual_machines
|
||||
join products on virtual_machines.sku=products.sku
|
||||
where user_id=$[_login_id]</sql>
|
||||
<ifrow>
|
||||
<sectionframe title="Virtual Machines">
|
||||
|
||||
<whilerow>
|
||||
|
||||
<div style="margin-bottom: 3px; border: 1pt solid #000; border-radius: 5px;">
|
||||
<div style="float: left; padding: 2px 5px 0px 5px; vertical-align: middle; display: inline-block;"><img src="$[.image]" width="40"></div>
|
||||
<div style="float: left; background: #ccf; width: 300px; padding: 0px 0px 0px 0px;"><span style="font-size: 7pt;">Ubuntu Server 22.04 LTE</span>
|
||||
<br><span style="font-size: 9pt;"><b>barant.com</b></span>
|
||||
<br><span style="font-size: 7pt;">IP:</span> <span style="font-size: 9pt; font-family: monospace;">74.80.233.78</span></div>
|
||||
|
||||
<div style="float: right; padding: 5px;"><img src="/assets/power_on.png" width="32"></div>
|
||||
<div style="float: right; width: 90px; height: 48px; background: #444;"></div>
|
||||
<div style="float: right; margin-right: 25px;">3 days 2:10:33<br><br>34% of 40.2GB</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
|
||||
</whilerow>
|
||||
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
|
||||
<include file="phones.section">
|
||||
|
||||
<sql>select *
|
||||
from files
|
||||
join products on files.sku=products.sku
|
||||
where user_id=$[_login_id]</sql>
|
||||
<ifrow>
|
||||
<sectionframe title="Downloadable Content">
|
||||
<p>Content that has been purchased and can be downloaded is displayed
|
||||
below. Click on the Download button to begin downloading your files.</p>
|
||||
|
||||
<whilerow>
|
||||
<table style="margin: 3px;">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="$[.image]" width="50px"">
|
||||
</td>
|
||||
<td style="width: 300px; border: 1pt inset #888">
|
||||
$[.description]
|
||||
</td>
|
||||
<td style="width: 300px;">
|
||||
<div>$[license_name]</div><div>$[license_key]</div>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/downloadfile.cgi?sku=$[.sku]"><div class="button">Download</div></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</whilerow>
|
||||
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
|
||||
<sectionframe title="Invoices">
|
||||
<div style="display: flex;">
|
||||
<div style="display: inline-block; padding: 0px 10px 0px 0px;">
|
||||
<showtable process="selectinvoice" name="invoice_id" value="X">
|
||||
select id as X,id as 'Invoice ID',date_format(created, '%b %D %Y') as 'Date',amount as 'Amount',status as 'Status' from invoices where user_id=$[_login_id]
|
||||
</showtable>
|
||||
</div>
|
||||
<if value1="$[_invoice_id]" value2="" type="ne">
|
||||
<div>
|
||||
<include file="invoice.method">
|
||||
<include file="payment.method">
|
||||
</div>
|
||||
</if>
|
||||
<div id="account-subpage">
|
||||
<if value1="$[SUBPAGE]" value2="" type="eq">
|
||||
<include file="account-info.subpage">
|
||||
<else>
|
||||
<try>
|
||||
<include file="account-$[SUBPAGE].subpage">
|
||||
<catch>
|
||||
<p>That account section doesn't exist.</p>
|
||||
</try>
|
||||
</if>
|
||||
</div>
|
||||
</sectionframe>
|
||||
|
||||
|
||||
</contents>
|
||||
</page>
|
||||
@@ -93,6 +93,16 @@
|
||||
box-shadow: 0 0 0.4em rgba(197, 164, 90, 0.25);
|
||||
transition: box-shadow 0.2s ease, background 0.2s ease, transform 0.1s ease;
|
||||
}
|
||||
/* .icon-btn's own display:inline-flex is a plain class selector -
|
||||
same specificity as the browser's own [hidden]{display:none} UA
|
||||
default, and an author rule always wins that tie regardless of
|
||||
source order - confirmed as a real, previously-shipped bug on a
|
||||
different site this same session (a hidden modal that stayed
|
||||
visible for the exact same reason). Without this, the empty-folder
|
||||
button's `hidden` attribute would be set correctly but silently
|
||||
ignored, leaving it visible on every folder instead of only
|
||||
Spam/Trash. */
|
||||
.icon-btn[hidden] { display: none; }
|
||||
.icon-btn svg { width: 16px; height: 16px; display: block; }
|
||||
.icon-btn:hover {
|
||||
box-shadow: 0 0 0.8em rgba(197, 164, 90, 0.5), 0 0 0.25em rgba(227, 196, 126, 0.55);
|
||||
@@ -118,12 +128,14 @@
|
||||
<div id="email-client">
|
||||
<div id="email-toolbar">
|
||||
<span id="email-connected-as">$[@_imap_user]</span><span id="email-list-count"></span>
|
||||
<span id="email-pagination"></span>
|
||||
<span id="email-toolbar-actions">
|
||||
<span id="email-search-box">
|
||||
<input type="text" id="email-search-input" placeholder="Search mail…">
|
||||
<button type="button" id="email-search-btn" class="icon-btn" title="Search"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.35-4.35"/></svg></button>
|
||||
</span>
|
||||
<button type="button" id="email-compose-btn" class="icon-btn" title="New Mail"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h13a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z"/><path d="M2.5 7.5 12 14l9.5-6.5"/><path d="M18.5 3.5v5M16 6h5"/></svg></button>
|
||||
<button type="button" id="email-empty-folder-btn" class="icon-btn" title="Permanently empty this folder" hidden><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16"/><path d="M9 7V4h6v3"/><path d="M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13"/><path d="M9.5 12.5l5 5M14.5 12.5l-5 5"/></svg></button>
|
||||
<button type="button" id="email-refresh-btn" class="icon-btn" title="Refresh"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11a8 8 0 0 0-14.6-4.4M4 4v5h5"/><path d="M4 13a8 8 0 0 0 14.6 4.4M20 20v-5h-5"/></svg></button>
|
||||
<button type="button" id="email-disconnect-btn" class="icon-btn" title="Disconnect"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/></svg></button>
|
||||
</span>
|
||||
@@ -135,4 +147,4 @@
|
||||
</div>
|
||||
</if>
|
||||
</div>
|
||||
<script src="/assets/email.js?v=20260907b"></script>
|
||||
<script src="/assets/email.js?v=20260926a"></script>
|
||||
@@ -0,0 +1,46 @@
|
||||
<include file="invoice.method">
|
||||
<br>
|
||||
<linkbutton page="editinvoice"><div class="button">Edit Invoice</div></linkbutton>
|
||||
<div style="margin-top: 10px; display: flex; align-items: center; gap: 6px;">
|
||||
<input type="email" id="mail_invoice_email" placeholder="recipient@example.com" style="width: 220px;">
|
||||
<button type="button" id="mail_invoice_btn" class="button">Mail Invoice</button>
|
||||
<span id="mail_invoice_status" style="font-size: 12px; color: var(--bond-text-dim);"></span>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var btn = document.getElementById('mail_invoice_btn');
|
||||
var input = document.getElementById('mail_invoice_email');
|
||||
var status = document.getElementById('mail_invoice_status');
|
||||
if (!btn || !input || !status) return;
|
||||
btn.addEventListener('click', function() {
|
||||
var email = input.value.trim();
|
||||
if (!email) {
|
||||
status.textContent = 'Enter an e-mail address first.';
|
||||
status.style.color = '#a13a3a';
|
||||
return;
|
||||
}
|
||||
btn.disabled = true;
|
||||
status.textContent = 'Sending…';
|
||||
status.style.color = 'var(--bond-text-dim)';
|
||||
fetch('/admin/mail-invoice', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ email: email }).toString()
|
||||
}).then(function(r) { return r.json(); }).then(function(res) {
|
||||
btn.disabled = false;
|
||||
if (res.ok) {
|
||||
status.textContent = 'Invoice emailed to ' + email + '.';
|
||||
status.style.color = '#6fb8c9';
|
||||
} else {
|
||||
status.textContent = res.error || 'Could not send the invoice.';
|
||||
status.style.color = '#a13a3a';
|
||||
}
|
||||
}).catch(function() {
|
||||
btn.disabled = false;
|
||||
status.textContent = 'Request failed. Please try again.';
|
||||
status.style.color = '#a13a3a';
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -1,5 +1,120 @@
|
||||
<retain name="invoice_id">
|
||||
<h3>Invoices</h3>
|
||||
<showtable page="admin_invoice" process="selectinvoice" name="invoice_id" value="X">
|
||||
select invoices.id as X,invoices.id,user_id,name,invoices.created,amount,invoices.status from invoices join users on invoices.user_id=users.id
|
||||
</showtable>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<button type="button" id="new_invoice_toggle" class="button">+ Create New Invoice</button>
|
||||
<div id="new_invoice_form" style="display: none; margin-top: 8px; align-items: center; gap: 6px;">
|
||||
<select id="new_invoice_user">
|
||||
<option value="">Select a customer…</option>
|
||||
<sql>select id,name,email from users order by name</sql>
|
||||
<whilerow>
|
||||
<option value="$[.id]">$[.name] ($[.email])</option>
|
||||
</whilerow>
|
||||
</select>
|
||||
<button type="button" id="new_invoice_create_btn" class="button">Create</button>
|
||||
<span id="new_invoice_status" style="font-size: 12px; color: var(--bond-text-dim);"></span>
|
||||
</div>
|
||||
</div>
|
||||
<span id="copy_invoice_status" style="font-size: 12px; color: var(--bond-text-dim);"></span>
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>id</th>
|
||||
<th>user_id</th>
|
||||
<th>name</th>
|
||||
<th>created</th>
|
||||
<th>amount</th>
|
||||
<th>status</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<sql>select invoices.id,user_id,name,invoices.created,amount,invoices.status from invoices join users on invoices.user_id=users.id</sql>
|
||||
<whilerow>
|
||||
<tr>
|
||||
<td><linkbutton page="admin" subpage="invoice" process="selectinvoice" name="invoice_id" value="$[.id]" class="button">Open</linkbutton></td>
|
||||
<td>$[.id]</td>
|
||||
<td>$[.user_id]</td>
|
||||
<td>$[.name]</td>
|
||||
<td>$[.created]</td>
|
||||
<td>$[.amount]</td>
|
||||
<td>$[.status]</td>
|
||||
<td><button type="button" class="button copy_invoice_btn" data-invoice-id="$[.id]">Copy</button></td>
|
||||
</tr>
|
||||
</whilerow>
|
||||
</table>
|
||||
<script>
|
||||
(function() {
|
||||
var toggle = document.getElementById('new_invoice_toggle');
|
||||
var form = document.getElementById('new_invoice_form');
|
||||
var userSelect = document.getElementById('new_invoice_user');
|
||||
var createBtn = document.getElementById('new_invoice_create_btn');
|
||||
var status = document.getElementById('new_invoice_status');
|
||||
if (!toggle || !form || !userSelect || !createBtn || !status) return;
|
||||
|
||||
toggle.addEventListener('click', function() {
|
||||
form.style.display = form.style.display === 'none' ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
createBtn.addEventListener('click', function() {
|
||||
var userId = userSelect.value;
|
||||
if (!userId) {
|
||||
status.textContent = 'Please select a customer.';
|
||||
status.style.color = '#a13a3a';
|
||||
return;
|
||||
}
|
||||
createBtn.disabled = true;
|
||||
status.textContent = 'Creating…';
|
||||
status.style.color = 'var(--bond-text-dim)';
|
||||
fetch('/admin/create-invoice', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ user_id: userId }).toString()
|
||||
}).then(function(r) { return r.json(); }).then(function(res) {
|
||||
if (res.ok) {
|
||||
window.location.href = '/editinvoice';
|
||||
} else {
|
||||
createBtn.disabled = false;
|
||||
status.textContent = res.error || 'Could not create the invoice.';
|
||||
status.style.color = '#a13a3a';
|
||||
}
|
||||
}).catch(function() {
|
||||
createBtn.disabled = false;
|
||||
status.textContent = 'Request failed. Please try again.';
|
||||
status.style.color = '#a13a3a';
|
||||
});
|
||||
});
|
||||
|
||||
var copyStatus = document.getElementById('copy_invoice_status');
|
||||
document.querySelectorAll('.copy_invoice_btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var sourceId = btn.getAttribute('data-invoice-id');
|
||||
document.querySelectorAll('.copy_invoice_btn').forEach(function(b) { b.disabled = true; });
|
||||
if (copyStatus) {
|
||||
copyStatus.textContent = 'Copying…';
|
||||
copyStatus.style.color = 'var(--bond-text-dim)';
|
||||
}
|
||||
fetch('/admin/copy-invoice', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ source_invoice_id: sourceId }).toString()
|
||||
}).then(function(r) { return r.json(); }).then(function(res) {
|
||||
if (res.ok) {
|
||||
window.location.href = '/editinvoice';
|
||||
} else {
|
||||
document.querySelectorAll('.copy_invoice_btn').forEach(function(b) { b.disabled = false; });
|
||||
if (copyStatus) {
|
||||
copyStatus.textContent = res.error || 'Could not copy the invoice.';
|
||||
copyStatus.style.color = '#a13a3a';
|
||||
}
|
||||
}
|
||||
}).catch(function() {
|
||||
document.querySelectorAll('.copy_invoice_btn').forEach(function(b) { b.disabled = false; });
|
||||
if (copyStatus) {
|
||||
copyStatus.textContent = 'Request failed. Please try again.';
|
||||
copyStatus.style.color = '#a13a3a';
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,98 @@
|
||||
<h3>Mail Accounts</h3>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<button type="button" id="new_mailaccount_toggle" class="button">+ Add Mail Account</button>
|
||||
<div id="new_mailaccount_form" style="display: none; margin-top: 8px; align-items: center; gap: 6px;">
|
||||
<input type="text" id="new_mailaccount_host" placeholder="Mail Server" value="mail.barant.com">
|
||||
<input type="text" id="new_mailaccount_email" placeholder="E-Mail Address">
|
||||
<input type="password" id="new_mailaccount_password" placeholder="Password">
|
||||
<button type="button" id="new_mailaccount_create_btn" class="button">Add</button>
|
||||
<span id="new_mailaccount_status" style="font-size: 12px; color: var(--bond-text-dim);"></span>
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>E-Mail</th>
|
||||
<th>Server</th>
|
||||
<th>Added</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<sql>select id,email,host,created from email_accounts where user_id=$[@_login_id] order by email</sql>
|
||||
<whilerow>
|
||||
<tr>
|
||||
<td>$[.email]</td>
|
||||
<td>$[.host]</td>
|
||||
<td>$[.created]</td>
|
||||
<td><button type="button" class="button remove_mailaccount_btn" data-account-id="$[.id]">Remove</button></td>
|
||||
</tr>
|
||||
</whilerow>
|
||||
</table>
|
||||
<p style="font-size: 12px; color: var(--bond-text-dim);">Saved accounts automatically reconnect the next time you log in.</p>
|
||||
<script>
|
||||
(function() {
|
||||
var toggle = document.getElementById('new_mailaccount_toggle');
|
||||
var form = document.getElementById('new_mailaccount_form');
|
||||
var hostInput = document.getElementById('new_mailaccount_host');
|
||||
var emailInput = document.getElementById('new_mailaccount_email');
|
||||
var passwordInput = document.getElementById('new_mailaccount_password');
|
||||
var createBtn = document.getElementById('new_mailaccount_create_btn');
|
||||
var status = document.getElementById('new_mailaccount_status');
|
||||
if (!toggle || !form || !hostInput || !emailInput || !passwordInput || !createBtn || !status) return;
|
||||
|
||||
toggle.addEventListener('click', function() {
|
||||
form.style.display = form.style.display === 'none' ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
createBtn.addEventListener('click', function() {
|
||||
var host = hostInput.value.trim();
|
||||
var email = emailInput.value.trim();
|
||||
var password = passwordInput.value;
|
||||
if (!host || !email || !password) {
|
||||
status.textContent = 'Please enter a mail server, e-mail address, and password.';
|
||||
status.style.color = '#a13a3a';
|
||||
return;
|
||||
}
|
||||
createBtn.disabled = true;
|
||||
status.textContent = 'Connecting…';
|
||||
status.style.color = 'var(--bond-text-dim)';
|
||||
fetch('/admin/add-mail-account', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ mail_host: host, mail_email: email, mail_password: password }).toString()
|
||||
}).then(function(r) { return r.json(); }).then(function(res) {
|
||||
if (res.ok) {
|
||||
window.location.href = '/admin/mailaccounts';
|
||||
} else {
|
||||
createBtn.disabled = false;
|
||||
status.textContent = res.error || 'Could not add the account.';
|
||||
status.style.color = '#a13a3a';
|
||||
}
|
||||
}).catch(function() {
|
||||
createBtn.disabled = false;
|
||||
status.textContent = 'Request failed. Please try again.';
|
||||
status.style.color = '#a13a3a';
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.remove_mailaccount_btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var accountId = btn.getAttribute('data-account-id');
|
||||
document.querySelectorAll('.remove_mailaccount_btn').forEach(function(b) { b.disabled = true; });
|
||||
fetch('/admin/remove-mail-account', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ account_id: accountId }).toString()
|
||||
}).then(function(r) { return r.json(); }).then(function(res) {
|
||||
if (res.ok) {
|
||||
window.location.href = '/admin/mailaccounts';
|
||||
} else {
|
||||
document.querySelectorAll('.remove_mailaccount_btn').forEach(function(b) { b.disabled = false; });
|
||||
}
|
||||
}).catch(function() {
|
||||
document.querySelectorAll('.remove_mailaccount_btn').forEach(function(b) { b.disabled = false; });
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -1,8 +1,29 @@
|
||||
<sectionframe title="ADMINISTRATIVE SUPPORT">
|
||||
<if value1="$[SUBPAGE]" value2="email" type="eq">
|
||||
<linkbutton page="admin" subpage="email" class="submenuitem-active">EMAIL</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="admin" subpage="email">EMAIL</linkbutton><br>
|
||||
</if>
|
||||
<if expr="('$[SUBPAGE]'='invoices') or ('$[SUBPAGE]'='invoice')">
|
||||
<linkbutton page="admin" subpage="invoices" class="submenuitem-active">INVOICES</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="admin" subpage="invoices">INVOICES</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="products" type="eq">
|
||||
<linkbutton page="admin" subpage="products" class="submenuitem-active">PRODUCTS</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="admin" subpage="products">PRODUCTS</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="users" type="eq">
|
||||
<linkbutton page="admin" subpage="users" class="submenuitem-active">USERS</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="admin" subpage="users">USERS</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="mailaccounts" type="eq">
|
||||
<linkbutton page="admin" subpage="mailaccounts" class="submenuitem-active">MAIL ACCOUNTS</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="admin" subpage="mailaccounts">MAIL ACCOUNTS</linkbutton><br>
|
||||
</if>
|
||||
</sectionframe>
|
||||
<if value1="$[SUBPAGE]" value2="email" type="eq">
|
||||
<include file="email.menu">
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
<title>ADMINISTRATION</title>
|
||||
<contents>
|
||||
<if value1="$[SUBPAGE]" value2="email" type="eq">
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
<p>Requested page is not found.</p>
|
||||
<else>
|
||||
<include file="admin-email.subpage">
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[SUBPAGE]" value2="newemail" type="eq">
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
<p>Requested page is not found.</p>
|
||||
<else>
|
||||
<include file="admin-newemail.subpage">
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[SUBPAGE]" value2="invoices" type="eq">
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
@@ -13,6 +21,13 @@
|
||||
<else>
|
||||
<include file="admin-invoices.subpage">
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[SUBPAGE]" value2="invoice" type="eq">
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
<p>Requested page is not found.</p>
|
||||
<else>
|
||||
<include file="admin-invoice.subpage">
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[SUBPAGE]" value2="users" type="eq">
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
@@ -27,6 +42,13 @@
|
||||
<else>
|
||||
<include file="admin-products.subpage">
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[SUBPAGE]" value2="mailaccounts" type="eq">
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
<p>Requested page is not found.</p>
|
||||
<else>
|
||||
<include file="admin-mailaccounts.subpage">
|
||||
</if>
|
||||
<else>
|
||||
<if expr="('$[_login_type]'='user')">
|
||||
<p>Requested page is not found.</p>
|
||||
@@ -40,6 +62,8 @@
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</contents>
|
||||
</page>
|
||||
@@ -1,11 +0,0 @@
|
||||
<page secure="yes" admin="true" loggedin="yes">
|
||||
<title>INVOICE</title>
|
||||
<contents>
|
||||
<eval name="_menu">
|
||||
<include file="adminmenu.section">
|
||||
</eval>
|
||||
<include file="invoice.method">
|
||||
<br>
|
||||
<linkbutton page="editinvoice"><div class="button">Edit Invoice</div></linkbutton>
|
||||
</contents>
|
||||
</page>
|
||||
@@ -1,4 +1,4 @@
|
||||
<sectionframe title="Admin Functions">
|
||||
<div><linkbutton page="modular1_1_preset_admin">Modular 1 Presets</linkbutton></div>
|
||||
<div><linkbutton page="admin_invoices">Invoices</linkbutton></div>
|
||||
<div><linkbutton page="admin" subpage="invoices">Invoices</linkbutton></div>
|
||||
</sectionframe>
|
||||
@@ -95,7 +95,7 @@
|
||||
</if>
|
||||
</tag>
|
||||
|
||||
<tag name="showtable" keywords="sessionid page process name value">
|
||||
<tag name="showtable" keywords="sessionid page subpage process name value">
|
||||
<sql sessionid="#[sessionid]"><container></sql>$[sqlerror]
|
||||
<ifrow sessionid="#[sessionid]">
|
||||
<table>
|
||||
@@ -117,7 +117,7 @@
|
||||
<set name="field" value="$[?$[index]]">
|
||||
<if value1="$[field]" value2="X" type="eq">
|
||||
<td>
|
||||
<linkbutton page="#[page]" process="#[process]" name="#[name]" value="$[#[value]]" class="button">Open</linkbutton>
|
||||
<linkbutton page="#[page]" subpage="#[subpage]" process="#[process]" name="#[name]" value="$[#[value]]" class="button">Open</linkbutton>
|
||||
</td>
|
||||
<else>
|
||||
<if expr="substring('$[field]',1,1)!='_'">
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#api POST /admin/copy-invoice
|
||||
<set name="host" value="localhost">
|
||||
<set name="database" value="barant">
|
||||
<set name="user" value="barant">
|
||||
<set name="password" value="uversa1960">
|
||||
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="">
|
||||
<header name="Content-Type" value="application/json">
|
||||
<if value1="$[@_login_type]" value2="admin" type="ne">
|
||||
{"ok":false,"error":"Not authorized."}
|
||||
<else>
|
||||
<if value1="$[source_invoice_id]" value2="" type="eq">
|
||||
{"ok":false,"error":"Please select an invoice to copy."}
|
||||
<else>
|
||||
<sql>select * from invoices where id=$[source_invoice_id]</sql>
|
||||
<ifrow>
|
||||
<sql>insert into invoices set user_id=$[.user_id], created=now(), amount=$[.amount], status="OPEN"</sql>
|
||||
<sql>select last_insert_id() as new_invoice_id</sql>
|
||||
<set name="new_invoice_id" value="$[.new_invoice_id]">
|
||||
<sql>insert into invoices_detail (invoice_id,sku,sku_suffix,quantity,description,text,price,total,tax_amount,type)
|
||||
select $[new_invoice_id],sku,sku_suffix,quantity,description,text,price,total,tax_amount,type
|
||||
from invoices_detail where invoice_id=$[source_invoice_id]</sql>
|
||||
<set name="@_invoice_id" value="$[new_invoice_id]">
|
||||
{"ok":true,"invoice_id":$[new_invoice_id]}
|
||||
<else>
|
||||
{"ok":false,"error":"Invoice not found."}
|
||||
</ifrow>
|
||||
</if>
|
||||
</if>
|
||||
</database>
|
||||
@@ -0,0 +1,21 @@
|
||||
#api POST /admin/create-invoice
|
||||
<set name="host" value="localhost">
|
||||
<set name="database" value="barant">
|
||||
<set name="user" value="barant">
|
||||
<set name="password" value="uversa1960">
|
||||
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="">
|
||||
<header name="Content-Type" value="application/json">
|
||||
<if value1="$[@_login_type]" value2="admin" type="ne">
|
||||
{"ok":false,"error":"Not authorized."}
|
||||
<else>
|
||||
<if value1="$[user_id]" value2="" type="eq">
|
||||
{"ok":false,"error":"Please select a user."}
|
||||
<else>
|
||||
<sql>insert into invoices set user_id=$[user_id], created=now(), amount=0.00, status="OPEN"</sql>
|
||||
<sql>select last_insert_id() as new_invoice_id</sql>
|
||||
<set name="new_invoice_id" value="$[.new_invoice_id]">
|
||||
<set name="@_invoice_id" value="$[new_invoice_id]">
|
||||
{"ok":true,"invoice_id":$[new_invoice_id]}
|
||||
</if>
|
||||
</if>
|
||||
</database>
|
||||
Executable → Regular
+100
-46
@@ -3,9 +3,6 @@
|
||||
<contents>
|
||||
<database host="$[host]" name="$[database]" user="$[user]" password="$[password]" sessionid="1">
|
||||
<script>
|
||||
function checkDetail() {
|
||||
document.getElementById('detail').style.display=(document.getElementById('sku').value=='***')?'block':'none';
|
||||
}
|
||||
function totalInvoice() {
|
||||
const detail_section = document.getElementById('detail_section');
|
||||
const totalsum = document.getElementById('totalsum');
|
||||
@@ -13,6 +10,7 @@ function totalInvoice() {
|
||||
var sum = 0;
|
||||
var index = 0;
|
||||
detail_section.childNodes.forEach((child) => {
|
||||
if (!child.quantity_z) return;
|
||||
child.quantity_z.setAttribute('name','quantity' + index);
|
||||
child.sku_z.setAttribute('name','sku' + index);
|
||||
child.description_z.setAttribute('name','description' + index);
|
||||
@@ -31,16 +29,18 @@ function totalInvoice() {
|
||||
}
|
||||
function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
|
||||
const lineItem = document.createElement('div');
|
||||
lineItem.style.border = "padding: 3px;";
|
||||
const lineItem = document.createElement('tr');
|
||||
|
||||
column1 = document.createElement('div');
|
||||
column1.setAttribute('style','display: inline-block; margin-right: 5px;');
|
||||
column1 = document.createElement('td');
|
||||
column1.setAttribute('style','text-align: center; vertical-align: top; padding: 6px 4px; border-bottom: 1px solid #000;');
|
||||
removeButton = document.createElement('button');
|
||||
removeButton.setAttribute('type','button');
|
||||
removeButton.setAttribute('class','button');
|
||||
removeButton.setAttribute('style','padding: 1px 7px 2px 7px; font-size: 11pt; line-height: 1;');
|
||||
removeButton.innerText = '-';
|
||||
removeButton.addEventListener('click', function(e) {
|
||||
document.getElementById('detail_section').removeChild(lineItem);
|
||||
if (lineItem.detailRow) document.getElementById('detail_section').removeChild(lineItem.detailRow);
|
||||
totalInvoice();
|
||||
});
|
||||
column1.appendChild(removeButton)
|
||||
@@ -66,11 +66,10 @@ function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
lineItem.total_z = total;
|
||||
lineItem.type_z = type;
|
||||
|
||||
column2 = document.createElement('div');
|
||||
column2.setAttribute('style','display: inline-block; margin-right: 5px;');
|
||||
column2 = document.createElement('td');
|
||||
column2.setAttribute('style','width: 54px; vertical-align: top; padding: 6px 4px; border-bottom: 1px solid #000;');
|
||||
quantity.setAttribute('type','text');
|
||||
quantity.setAttribute('size','5');
|
||||
quantity.setAttribute('maxlength','5');
|
||||
quantity.setAttribute('style','width: 44px; text-align: center;');
|
||||
quantity.setAttribute('name','quantity');
|
||||
quantity.setAttribute('value',qty);
|
||||
quantity.addEventListener('change',(e) => {
|
||||
@@ -83,9 +82,10 @@ function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
column2.appendChild(quantity);
|
||||
lineItem.appendChild(column2);
|
||||
|
||||
column3 = document.createElement('div');
|
||||
column3.setAttribute('style','display: inline-block; margin-right: 5px;');
|
||||
column3 = document.createElement('td');
|
||||
column3.setAttribute('style','vertical-align: top; padding: 6px 4px; border-bottom: 1px solid #000;');
|
||||
sku.setAttribute('name','sku');
|
||||
sku.setAttribute('style','width: 100%;');
|
||||
sku.detail = detail;
|
||||
sku.addEventListener('change', (e) => {
|
||||
sku.detail.style.display = sku.value == '***' ? 'block':'none';
|
||||
@@ -99,13 +99,16 @@ function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
});
|
||||
<sql sessionid="1">select * from product_list</sql>
|
||||
<whilerow sessionid="1">
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[1.description]" name="product_description_js">
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[1.sku]" name="product_sku_js">
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[1.type]" name="product_type_js">
|
||||
option = document.createElement('option');
|
||||
option.setAttribute('value','$[1.sku]');
|
||||
option.description = '$[1.description]';
|
||||
option.typex = '$[1.type]';
|
||||
option.setAttribute('value',$[product_sku_js]);
|
||||
option.description = $[product_description_js];
|
||||
option.typex = $[product_type_js];
|
||||
option.price = '$[1.price]';
|
||||
option.innerText = '$[1.description]';
|
||||
if(skuid == '$[1.sku]') {
|
||||
option.innerText = $[product_description_js];
|
||||
if(skuid == $[product_sku_js]) {
|
||||
option.selected = 'selected';
|
||||
}
|
||||
sku.appendChild(option);
|
||||
@@ -121,47 +124,52 @@ function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
type.setAttribute('value', typ);
|
||||
lineItem.appendChild(type);
|
||||
|
||||
column4 = document.createElement('div');
|
||||
column4.setAttribute('style','display: inline-block; margin-right: 5px;');
|
||||
column4 = document.createElement('td');
|
||||
column4.setAttribute('style','width: 90px; vertical-align: top; padding: 6px 4px; border-bottom: 1px solid #000;');
|
||||
price.setAttribute('type','text');
|
||||
price.setAttribute('size','15');
|
||||
price.setAttribute('maxlength','15');
|
||||
price.setAttribute('style','width: 80px; text-align: right;');
|
||||
price.setAttribute('name','price');
|
||||
price.setAttribute('value',prc);
|
||||
column4.appendChild(price);
|
||||
lineItem.appendChild(column4);
|
||||
|
||||
column5 = document.createElement('div');
|
||||
column5.setAttribute('style','display: inline-block; margin-right: 5px;');
|
||||
column5 = document.createElement('td');
|
||||
column5.setAttribute('style','width: 70px; vertical-align: top; padding: 6px 4px; border-bottom: 1px solid #000;');
|
||||
taxAmount.setAttribute('type','text');
|
||||
taxAmount.setAttribute('size','15');
|
||||
taxAmount.setAttribute('maxlength','15');
|
||||
taxAmount.setAttribute('style','width: 60px; text-align: right;');
|
||||
taxAmount.setAttribute('name','tax_amount');
|
||||
taxAmount.setAttribute('value',tax);
|
||||
column5.appendChild(taxAmount);
|
||||
lineItem.appendChild(column5);
|
||||
|
||||
column6 = document.createElement('div');
|
||||
column6.setAttribute('style','display: inline-block;');
|
||||
column6 = document.createElement('td');
|
||||
column6.setAttribute('style','width: 90px; vertical-align: top; padding: 6px 4px; border-bottom: 1px solid #000;');
|
||||
total.setAttribute('type','text');
|
||||
total.setAttribute('size','15');
|
||||
total.setAttribute('maxlength','15');
|
||||
total.setAttribute('style','width: 80px; text-align: right;');
|
||||
total.setAttribute('name','total');
|
||||
total.setAttribute('value',tot);
|
||||
column6.appendChild(total);
|
||||
lineItem.appendChild(column6);
|
||||
|
||||
const detailRow = document.createElement('tr');
|
||||
const detailCell = document.createElement('td');
|
||||
detailCell.setAttribute('colspan','6');
|
||||
detailCell.setAttribute('style','padding: 0 4px 6px 4px; border-bottom: 1px solid #000;');
|
||||
textarea.setAttribute('name','textarea');
|
||||
textarea.setAttribute('rows','5');
|
||||
textarea.setAttribute('style','width: 100%; background: #101014; color: #e7e4dc; border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 2px; padding: 6px 8px; font-family: inherit; font-size: 14px;');
|
||||
textarea.innerHTML = text;
|
||||
CKEDITOR.replace(textarea);
|
||||
detail.appendChild(textarea);
|
||||
lineItem.appendChild(detail);
|
||||
detailCell.appendChild(detail);
|
||||
detailRow.appendChild(detailCell);
|
||||
lineItem.detailRow = detailRow;
|
||||
|
||||
detail.style.display = sku.value == '***' ? 'block':'none';
|
||||
|
||||
lineItem.total = total.value;
|
||||
|
||||
document.getElementById('detail_section').appendChild(lineItem);
|
||||
document.getElementById('detail_section').appendChild(detailRow);
|
||||
}
|
||||
</script>
|
||||
<input type="hidden" id="linecount" name="linecount">
|
||||
@@ -169,12 +177,30 @@ function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
<eval name="_menu">
|
||||
<include file="adminmenu.section">
|
||||
</eval>
|
||||
<h3>Invoice $[_invoice_id]</h3>
|
||||
<sql>select * from invoices where id=$[_invoice_id]</sql>
|
||||
<entryform>
|
||||
<td>Account</td>
|
||||
<td>
|
||||
<select>
|
||||
<sql>select i.id as invnumber,
|
||||
u.name as name,
|
||||
u.company_name as company_name,
|
||||
u.email as email,
|
||||
date_format(i.created,'%m/%e/%Y') as invdate,
|
||||
i.status as status,
|
||||
i.user_id as user_id
|
||||
from invoices as i
|
||||
join users as u on i.user_id=u.id
|
||||
where i.id=$[@_invoice_id]</sql>
|
||||
<ifrow>
|
||||
<div style="width: 760px; max-width: 100%; margin: 0 auto; border: 1px solid rgba(197, 164, 90, 0.28); border-radius: 10px; padding: 20px; background: #0a0a0d; color: #e7e4dc; font-family: Arial, Helvetica, sans-serif; font-size: 14px;">
|
||||
<table style="width: 100%; border-collapse: collapse;" cellspacing="0" cellpadding="0"><tr>
|
||||
<td style="vertical-align: middle;"><img style="height: 90px; width: auto;" src="/assets/btglogo.png"></td>
|
||||
<td style="vertical-align: middle; text-align: right; color: #c5a45a; letter-spacing: 0.5px;">
|
||||
<div style="font-size: 24px; font-weight: 600;">Invoice: $[.invnumber]</div>
|
||||
<div style="color: #8d8c92; font-size: 12px; margin-top: 4px;">$[.status]</div>
|
||||
</td>
|
||||
</tr></table>
|
||||
<div style="height: 1px; background: rgba(197, 164, 90, 0.28); margin: 16px 0;"></div>
|
||||
<table style="border-collapse: collapse; margin-bottom: 16px; font-size: 16px; width: 100%;" cellspacing="0" cellpadding="0">
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px; border-bottom: 1px solid #000; width: 150px;">Account:</td>
|
||||
<td style="padding: 3px 16px 3px 0; border-bottom: 1px solid #000;">
|
||||
<select name="user_id" style="width: 100%; max-width: 360px;">
|
||||
<sql sessionid="1">select * from users</sql>
|
||||
<whilerow sessionid="1">
|
||||
<option value="$[1.id]"
|
||||
@@ -183,23 +209,51 @@ function addLine(qty,skuid,descr,text,prc,tax,tot,typ) {
|
||||
</whilerow>
|
||||
</select>
|
||||
</td></tr>
|
||||
<tr><td colspan="3">
|
||||
<div id="detail_section"></div>
|
||||
<sql>select * from invoices_detail where invoice_id=$[_invoice_id]</sql>
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px; border-bottom: 1px solid #000;">Company Name:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0; border-bottom: 1px solid #000;">$[.company_name]</td></tr>
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px; border-bottom: 1px solid #000;">E-Mail:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0; border-bottom: 1px solid #000;">$[.email]</td></tr>
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px;">Invoice Date:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0;">$[.invdate]</td></tr>
|
||||
</table>
|
||||
|
||||
<table style="width: 100%; border-collapse: collapse; background: #16161c; border-radius: 6px;" cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr><td style="background-color: #1c1c24; color: #c5a45a; width: 54px; padding: 6px 4px; text-align: center; border-bottom: 1px solid #000;"></td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 54px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Qty</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; padding: 6px 8px; border-bottom: 1px solid #000;">Item / Description</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 90px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Unit Price</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 70px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Tax</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 90px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Amount</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="detail_section"></tbody>
|
||||
<tfoot>
|
||||
<tr><td colspan="5" style="text-align: right; padding: 10px 8px; color: #e3c47e; font-weight: bold;">Invoice Total:</td>
|
||||
<td id="totalsum" style="text-align: right; padding: 10px 8px; color: #e3c47e; font-weight: bold;"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<sql>select * from invoices_detail where invoice_id=$[@_invoice_id]</sql>
|
||||
<whilerow>
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[.sku]" name="detail_sku_js">
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[.description]" name="detail_description_js">
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[.text]" name="detail_text_js">
|
||||
<call pgm="/bin/sh" arg1="-c" arg2="jq -R -s . | sed 's#/#\\/#g'" input="$[.type]" name="detail_type_js">
|
||||
<script>
|
||||
addLine('$[.quantity]','$[.sku]','$[.description]','$[.text]','$[.price]','$[.tax_amount]','$[.total]','$[.type]');
|
||||
addLine('$[.quantity]',$[detail_sku_js],$[detail_description_js],$[detail_text_js],'$[.price]','$[.tax_amount]','$[.total]',$[detail_type_js]);
|
||||
</script>
|
||||
</whilerow>
|
||||
<button type="button" onclick="addLine('1','','','','0.00','0.00','0.00','');">+</button>
|
||||
<div id="totalsum" style="border: 1pt solid #000f; padding: 3px; width: 100px; text-align: right; float: right;"></div>
|
||||
<div style="margin-top: 10px;">
|
||||
<button type="button" class="button" onclick="addLine('1','','','','0.00','0.00','0.00','');">+ Add Line</button>
|
||||
</div>
|
||||
<script>
|
||||
totalInvoice();
|
||||
</script>
|
||||
<buttonbay>
|
||||
<buttonbay style="display: block; margin-top: 18px; text-align: right;">
|
||||
<linkbutton process="update_invoice"><div class="button">Update Invoice</div></linkbutton>
|
||||
</buttonbay>
|
||||
</entryform>
|
||||
</div>
|
||||
<else>
|
||||
<div style="width: 760px; max-width: 100%; margin: 40px auto; text-align: center; color: #8d8c92;">Invoice not found.</div>
|
||||
</ifrow>
|
||||
<br>
|
||||
</database>
|
||||
</contents>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#api POST /email/message
|
||||
#api POST /email/flag
|
||||
#api POST /email/delete
|
||||
#api POST /email/emptyfolder
|
||||
#api POST /email/trash
|
||||
#api POST /email/folders
|
||||
#api POST /email/search
|
||||
@@ -12,10 +13,15 @@
|
||||
#api POST /email/switchaccount
|
||||
<header name="Content-Type" value="application/json">
|
||||
<if value1="$[REQUEST_URI]" value2="/email/connect" type="eq">
|
||||
<if value1="$[host]" value2="" type="eq">
|
||||
<set name="host" value="mail.barant.com">
|
||||
</if>
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[user]" password="$[password]" sessionid="">
|
||||
<eval name="_imap_accounts"><imapaccounts action="add" list="$[@_imap_accounts]" user="$[user]" password="$[password]"></imapaccounts></eval>
|
||||
<imap config="./email.cfg" host="$[host]" user="$[user]" password="$[password]" sessionid="">
|
||||
<eval name="_imap_accounts"><imapaccounts action="add" list="$[@_imap_accounts]" host="$[host]" user="$[user]" password="$[password]"></imapaccounts></eval>
|
||||
<set name="@_imap_accounts" value="$[_imap_accounts]">
|
||||
<set name="_imap_host" value="$[host]">
|
||||
<set name="@_imap_host" value="$[host]">
|
||||
<set name="_imap_user" value="$[user]">
|
||||
<set name="@_imap_user" value="$[user]">
|
||||
<set name="_imap_password" value="$[password]">
|
||||
@@ -24,7 +30,6 @@
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/disconnect" type="eq">
|
||||
@@ -36,22 +41,25 @@
|
||||
</if>
|
||||
<eval name="_next_user"><imapaccounts action="firstuser" list="$[@_imap_accounts]"></imapaccounts></eval>
|
||||
<if value1="$[_next_user]" value2="" type="eq">
|
||||
<set name="@_imap_host" value="">
|
||||
<set name="@_imap_user" value="">
|
||||
<set name="@_imap_password" value="">
|
||||
{"ok":true,"active":""}
|
||||
<else>
|
||||
<try>
|
||||
<eval name="_next_host"><imapaccounts action="gethost" list="$[@_imap_accounts]" user="$[_next_user]"></imapaccounts></eval>
|
||||
<eval name="_next_password"><imapaccounts action="getpassword" list="$[@_imap_accounts]" user="$[_next_user]"></imapaccounts></eval>
|
||||
<imap config="./email.cfg" user="$[_next_user]" password="$[_next_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[_next_host]" user="$[_next_user]" password="$[_next_password]" sessionid="">
|
||||
<set name="@_imap_host" value="$[_next_host]">
|
||||
<set name="@_imap_user" value="$[_next_user]">
|
||||
<set name="@_imap_password" value="$[_next_password]">
|
||||
{"ok":true,"active":"$[_next_user]"}
|
||||
</imap>
|
||||
<catch name="_disconnecterr">
|
||||
<set name="@_imap_host" value="">
|
||||
<set name="@_imap_user" value="">
|
||||
<set name="@_imap_password" value="">
|
||||
{"ok":true,"active":""}
|
||||
</catch>
|
||||
</try>
|
||||
</if>
|
||||
<else>
|
||||
@@ -63,7 +71,7 @@
|
||||
</if>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/list" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<if value1="$[limit]" value2="" type="eq">
|
||||
<set name="limit" value="50">
|
||||
</if>
|
||||
@@ -71,67 +79,82 @@
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/message" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapmessage sessionid="" folder="$[folder]" uid="$[uid]">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/flag" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapflag sessionid="" folder="$[folder]" uid="$[uid]" flag="$[flag]" set="$[set]">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/delete" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapdelete sessionid="" folder="$[folder]" uid="$[uid]">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/emptyfolder" type="eq">
|
||||
<if value1="$[folder]" value2="Spam" type="eq">
|
||||
<set name="_emptyok" value="1">
|
||||
<else>
|
||||
<if value1="$[folder]" value2="Trash" type="eq">
|
||||
<set name="_emptyok" value="1">
|
||||
<else>
|
||||
<set name="_emptyok" value="0">
|
||||
</if>
|
||||
</if>
|
||||
<if value1="$[_emptyok]" value2="1" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapemptyfolder sessionid="" folder="$[folder]">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</try>
|
||||
<else>
|
||||
{"ok":false,"error":"Only the Spam and Trash folders can be emptied."}
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/trash" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapmove sessionid="" folder="$[folder]" uid="$[uid]" destfolder="Trash">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/folders" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapfolders sessionid="">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/search" type="eq">
|
||||
<try>
|
||||
<imap config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[@_imap_host]" user="$[@_imap_user]" password="$[@_imap_password]" sessionid="">
|
||||
<imapsearch sessionid="" folder="$[folder]" query="$[query]">
|
||||
</imap>
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"$[_imaperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/send" type="eq">
|
||||
@@ -139,7 +162,6 @@
|
||||
<smtpsend config="./email.cfg" user="$[@_imap_user]" password="$[@_imap_password]" to="$[to]" subject="$[subject]" html="$[body]">
|
||||
<catch name="_smtperr">
|
||||
{"ok":false,"error":"$[_smtperr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/accounts" type="eq">
|
||||
@@ -147,11 +169,13 @@
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/email/switchaccount" type="eq">
|
||||
<try>
|
||||
<eval name="_switch_host"><imapaccounts action="gethost" list="$[@_imap_accounts]" user="$[user]"></imapaccounts></eval>
|
||||
<eval name="_switch_password"><imapaccounts action="getpassword" list="$[@_imap_accounts]" user="$[user]"></imapaccounts></eval>
|
||||
<if value1="$[_switch_password]" value2="" type="eq">
|
||||
{"ok":false,"error":"That account is not connected."}
|
||||
<else>
|
||||
<imap config="./email.cfg" user="$[user]" password="$[_switch_password]" sessionid="">
|
||||
<imap config="./email.cfg" host="$[_switch_host]" user="$[user]" password="$[_switch_password]" sessionid="">
|
||||
<set name="@_imap_host" value="$[_switch_host]">
|
||||
<set name="@_imap_user" value="$[user]">
|
||||
<set name="@_imap_password" value="$[_switch_password]">
|
||||
{"ok":true}
|
||||
@@ -159,7 +183,6 @@
|
||||
</if>
|
||||
<catch name="_switcherr">
|
||||
{"ok":false,"error":"$[_switcherr]"}
|
||||
</catch>
|
||||
</try>
|
||||
<else>
|
||||
{"ok":false,"error":"Unknown route."}
|
||||
@@ -175,4 +198,5 @@
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
@@ -7,52 +7,51 @@
|
||||
i.amount as amount
|
||||
from invoices as i
|
||||
join users as u on i.user_id=u.id
|
||||
where i.id=$[_invoice_id]</sql>
|
||||
where i.id=$[@_invoice_id]</sql>
|
||||
<set name="amount" value="$[.amount]">
|
||||
<div style="width: 500px; border: 1pt solid #000; padding: 3px; background: #fff;">
|
||||
<div><div style="display: inline-block;"><img style="width: 300px;" src="/assets/invoice_logo.png"></div>
|
||||
<div style="display: flex; float: right; align-items: center;">
|
||||
Invoice: $[.invnumber] $[.status]
|
||||
</div>
|
||||
</div>
|
||||
<div style="background: #eee;">
|
||||
<div>Name: $[.name]</div>
|
||||
<div>Company Name: $[.company_name]</div>
|
||||
<div>E-Mail $[.email]</div>
|
||||
<div>Invoice Date: $[.invdate]</div>
|
||||
</div>
|
||||
<div style="background: #ddd;">
|
||||
<sql>select * from invoices_detail where invoice_id=$[_invoice_id]</sql>
|
||||
<table style="border: 0px;" cellspacing="0">
|
||||
<tr><td style="background-color: #888; color: #fff; width: 50px; padding:3px; text-align: center; border: 1pt solid #ddd;">Qty</td>
|
||||
<td style="background-color: #888; color: #fff; width: 400px; padding: 3px; border: 1pt solid #ddd;">Description</td>
|
||||
<td style="background-color: #888; color: #fff; width: 60px; padding: 3px; text-align: center; border: 1pt solid #ddd;">Unit Price</td>
|
||||
<td style="background-color: #888; color: #fff; width: 60px; padding: 3px; text-align: center; border: 1pt solid #ddd;">Amount</td>
|
||||
<set name="invoicestatus" value="$[.status]">
|
||||
<div style="width: 600px; max-width: 100%; margin: 0 auto; border: 1px solid rgba(197, 164, 90, 0.28); border-radius: 10px; padding: 20px; background: #0a0a0d; color: #e7e4dc; font-family: Arial, Helvetica, sans-serif; font-size: 14px;">
|
||||
<table style="width: 100%; border-collapse: collapse;" cellspacing="0" cellpadding="0"><tr>
|
||||
<td style="vertical-align: middle;"><img style="height: 90px; width: auto;" src="https://barant.com/assets/btglogo.png"></td>
|
||||
<td style="vertical-align: middle; text-align: right; color: #c5a45a; letter-spacing: 0.5px;">
|
||||
<div style="font-size: 24px; font-weight: 600;">Invoice: $[.invnumber]</div>
|
||||
<div style="color: #8d8c92; font-size: 12px; margin-top: 4px;">$[.status]</div>
|
||||
</td>
|
||||
</tr></table>
|
||||
<div style="height: 1px; background: rgba(197, 164, 90, 0.28); margin: 16px 0;"></div>
|
||||
<table style="border-collapse: collapse; margin-bottom: 16px; font-size: 16px;" cellspacing="0" cellpadding="0">
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px; border-bottom: 1px solid #000;">Name:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0; border-bottom: 1px solid #000;">$[.name]</td></tr>
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px; border-bottom: 1px solid #000;">Company Name:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0; border-bottom: 1px solid #000;">$[.company_name]</td></tr>
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px; border-bottom: 1px solid #000;">E-Mail:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0; border-bottom: 1px solid #000;">$[.email]</td></tr>
|
||||
<tr><td style="color: #8d8c92; text-align: right; padding: 3px 10px 3px 16px;">Invoice Date:</td><td style="color: #e7e4dc; text-align: left; padding: 3px 16px 3px 0;">$[.invdate]</td></tr>
|
||||
</table>
|
||||
<sql>select * from invoices_detail where invoice_id=$[@_invoice_id]</sql>
|
||||
<table style="width: 100%; border-collapse: collapse; background: #16161c; border-radius: 6px;" cellspacing="0" cellpadding="0">
|
||||
<tr><td style="background-color: #1c1c24; color: #c5a45a; width: 50px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Qty</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 400px; padding: 6px 8px; border-bottom: 1px solid #000;">Description</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 60px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Unit Price</td>
|
||||
<td style="background-color: #1c1c24; color: #c5a45a; width: 60px; padding: 6px 8px; text-align: center; border-bottom: 1px solid #000;">Amount</td>
|
||||
</tr>
|
||||
<whilerow>
|
||||
<tr><td style="width: 50px; vertical-align: top; text-align: center; border: 1pt solid #ddd;">
|
||||
<tr><td style="width: 50px; vertical-align: top; text-align: center; color: #e7e4dc; padding: 6px 8px; border-bottom: 1px solid #000;">
|
||||
<if value1="$[.sku]" value2="***" type="ne">$[quantity]</if></td>
|
||||
<td style="width: 400px; border: 1pt solid #ddd;">
|
||||
<td style="width: 400px; vertical-align: top; color: #e7e4dc; padding: 6px 8px; border-bottom: 1px solid #000;">
|
||||
<if value1="$[.sku]" value2="***" type="ne">$[description]<br></if>
|
||||
$[text]</td>
|
||||
<td style="width: 60px; vertical-align: top; text-align: right; border: 1pt solid #ddd;">
|
||||
<td style="width: 60px; vertical-align: top; text-align: right; color: #e7e4dc; padding: 6px 8px; border-bottom: 1px solid #000;">
|
||||
<if value1="$[.sku]" value2="***" type="ne">$[price]</if></td>
|
||||
<td style="width: 60px; vertical-align: top; text-align: right; border: 1pt solid #ddd;">$[total]</td>
|
||||
<td style="width: 60px; vertical-align: top; text-align: right; color: #e7e4dc; padding: 6px 8px; border-bottom: 1px solid #000;">$[total]</td>
|
||||
</tr>
|
||||
</whilerow>
|
||||
<tr><td style="width: 50px; border: 0pt solid #000;"></td>
|
||||
<td style="width: 400px; text-align: right; border: 0pt solid #000;" colspan="2">Invoice Total:</td>
|
||||
<td style="width: 60px; text-align: right; border: 1pt solid #000;">$[amount]</td>
|
||||
<tr><td style="width: 50px;"></td>
|
||||
<td style="width: 400px; text-align: right; padding: 10px 8px; color: #e3c47e; font-weight: bold;" colspan="2">Invoice Total:</td>
|
||||
<td style="width: 60px; text-align: right; padding: 10px 8px; color: #e3c47e; font-weight: bold;">$[amount]</td>
|
||||
</tr>
|
||||
<tr><td colspan="4" style="width: 50px; border: 0pt solid #000;"><hr></td>
|
||||
</tr>
|
||||
<sql>select * from payments where invoice_id=$[_invoice_id]</sql>
|
||||
<whilerow>
|
||||
<tr><td style="width: 50px; border: 0pt solid #000;"></td>
|
||||
<td colspan="2" style="width: 400px; text-align: right; border: 0pt solid #000;">Credit Card: $[.card_brand] ending in $[.last_4_digits] expires on $[.exp_month]/$[.exp_year]</td>
|
||||
<td style="width: 60px; text-align: right; border: 1pt solid #000;">$[.amount]</td>
|
||||
</tr>
|
||||
</whilerow>
|
||||
</table>
|
||||
</div>
|
||||
</table>
|
||||
<sql>select * from payments where invoice_id=$[@_invoice_id]</sql>
|
||||
<whilerow>
|
||||
<div style="margin-top: 12px; text-align: right; color: #8d8c92; font-size: 12px;">
|
||||
Credit Card: $[.card_brand] ending in $[.last_4_digits] expires $[.exp_month]/$[.exp_year]
|
||||
</div>
|
||||
</whilerow>
|
||||
</div>
|
||||
@@ -1,67 +0,0 @@
|
||||
<page secure="yes" loggedin="no">
|
||||
<title>JUKEBOX</title>
|
||||
<contents>
|
||||
<script>
|
||||
var index = 0;
|
||||
const paths = [];
|
||||
const songs = [];
|
||||
function onselection(path,selection) {
|
||||
var name = path + '/' + selection;
|
||||
var player = document.getElementById('player');
|
||||
var audio = document.getElementById('audio');
|
||||
var title = document.getElementById('title');
|
||||
player.src = name;
|
||||
title.textContent = selection;
|
||||
audio.load();
|
||||
audio.play();
|
||||
}
|
||||
function selectNext() {
|
||||
var index = Math.floor(Math.random()*songs.length) + 1;
|
||||
onselection(paths[index],songs[index]);
|
||||
}
|
||||
</script>
|
||||
<retain name="download_file">
|
||||
<div style="display: inline-block;">
|
||||
<audio id="audio" controls onended="selectNext();">
|
||||
<source id="player" type="audio/mp3">
|
||||
</audio>
|
||||
</div>
|
||||
<div style="font-size: 20px; display: inline-block;" id="title">Click on a title below</div>
|
||||
<sectionframe title="Old Library">
|
||||
<div style="height: 300px; overflow-y: scroll;">
|
||||
<whiledir name="file" dir="musiclink/library">
|
||||
<if expr="left('$[file]',1) != '.' ">
|
||||
<div style="cursor: pointer;" onclick="onselection('musiclink/library','$[file]');">$[file]</div>
|
||||
<script>
|
||||
paths[index]='musiclink/library';
|
||||
songs[index++]='$[file]';
|
||||
</script>
|
||||
</if>
|
||||
</whiledir>
|
||||
</div>
|
||||
<script>
|
||||
</script>
|
||||
</sectionframe>
|
||||
|
||||
<sectionframe title="Ian's Library">
|
||||
<div style="height: 300px; overflow-y: scroll;">
|
||||
<whiledir name="file" dir="musiclink/ianslibrary">
|
||||
<if expr="left('$[file]',1) != '.' ">
|
||||
<div style="cursor: pointer;" onclick="onselection('musiclink/ianslibrary','$[file]');">$[file]</div>
|
||||
<script>
|
||||
paths[index]='musiclink/ianslibrary';
|
||||
songs[index++]='$[file]';
|
||||
</script>
|
||||
</if>
|
||||
</whiledir>
|
||||
</div>
|
||||
</sectionframe>
|
||||
<script>
|
||||
function printName(name) {
|
||||
document.write(name + '\n');
|
||||
}
|
||||
//songs.forEach(printName);
|
||||
</script>
|
||||
|
||||
</contents>
|
||||
</page>
|
||||
@@ -14,6 +14,19 @@
|
||||
<setenv name="_login_type">$[login_type]</setenv>
|
||||
<setenv name="_login_uuid">$[login_uuid]</setenv>
|
||||
<sql>update users set last_login=now() where id=$[login_id]</sql>
|
||||
<sql>select group_concat(to_base64(host),':',to_base64(email),':',to_base64(password) order by id separator ';') as accounts_list,
|
||||
(select host from email_accounts where user_id=$[login_id] order by id limit 1) as first_host,
|
||||
(select email from email_accounts where user_id=$[login_id] order by id limit 1) as first_email,
|
||||
(select password from email_accounts where user_id=$[login_id] order by id limit 1) as first_password
|
||||
from email_accounts where user_id=$[login_id]</sql>
|
||||
<ifrow>
|
||||
<if value1="$[.accounts_list]" value2="" type="ne">
|
||||
<set name="@_imap_accounts" value="$[.accounts_list]">
|
||||
<set name="@_imap_host" value="$[.first_host]">
|
||||
<set name="@_imap_user" value="$[.first_email]">
|
||||
<set name="@_imap_password" value="$[.first_password]">
|
||||
</if>
|
||||
</ifrow>
|
||||
<if value1="$[@start]" value2="" type="eq">
|
||||
<setpage name="account">
|
||||
<else>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#api POST /admin/mail-invoice
|
||||
<set name="host" value="localhost">
|
||||
<set name="database" value="barant">
|
||||
<set name="user" value="barant">
|
||||
<set name="password" value="uversa1960">
|
||||
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="">
|
||||
<header name="Content-Type" value="application/json">
|
||||
<if value1="$[@_login_type]" value2="admin" type="ne">
|
||||
{"ok":false,"error":"Not authorized."}
|
||||
<else>
|
||||
<if value1="$[@_invoice_id]" value2="" type="eq">
|
||||
{"ok":false,"error":"No invoice selected."}
|
||||
<else>
|
||||
<if value1="$[email]" value2="" type="eq">
|
||||
{"ok":false,"error":"Please enter an e-mail address."}
|
||||
<else>
|
||||
<try>
|
||||
<set name="_invoice_email_override" value="$[email]">
|
||||
<include file="send_invoice_email.method">{"ok":true}
|
||||
<catch name="_mailerr">
|
||||
{"ok":false,"error":"$[_mailerr]"}
|
||||
</try>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</database>
|
||||
@@ -0,0 +1,43 @@
|
||||
#api POST /admin/add-mail-account
|
||||
#api POST /admin/remove-mail-account
|
||||
<set name="host" value="localhost">
|
||||
<set name="database" value="barant">
|
||||
<set name="user" value="barant">
|
||||
<set name="password" value="uversa1960">
|
||||
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="">
|
||||
<header name="Content-Type" value="application/json">
|
||||
<if value1="$[@_login_type]" value2="admin" type="ne">
|
||||
{"ok":false,"error":"Not authorized."}
|
||||
<else>
|
||||
<if value1="$[REQUEST_URI]" value2="/admin/add-mail-account" type="eq">
|
||||
<if value1="$[mail_host]" value2="" type="eq">
|
||||
{"ok":false,"error":"Please enter a mail server."}
|
||||
<else>
|
||||
<if value1="$[mail_email]" value2="" type="eq">
|
||||
{"ok":false,"error":"Please enter an e-mail address."}
|
||||
<else>
|
||||
<if value1="$[mail_password]" value2="" type="eq">
|
||||
{"ok":false,"error":"Please enter a password."}
|
||||
<else>
|
||||
<try>
|
||||
<imap config="./email.cfg" host="$[mail_host]" user="$[mail_email]" password="$[mail_password]" sessionid="">
|
||||
</imap>
|
||||
<sql>insert into email_accounts (user_id,email,host,password) values ($[@_login_id],'$[mail_email]','$[mail_host]','$[mail_password]')
|
||||
on duplicate key update host='$[mail_host]', password='$[mail_password]'</sql>
|
||||
{"ok":true}
|
||||
<catch name="_imaperr">
|
||||
{"ok":false,"error":"Could not connect with those credentials: $[_imaperr]"}
|
||||
</try>
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
<else>
|
||||
<if value1="$[account_id]" value2="" type="eq">
|
||||
{"ok":false,"error":"No account specified."}
|
||||
<else>
|
||||
<sql>delete from email_accounts where id=$[account_id] and user_id=$[@_login_id]</sql>
|
||||
{"ok":true}
|
||||
</if>
|
||||
</if>
|
||||
</if>
|
||||
</database>
|
||||
@@ -0,0 +1,7 @@
|
||||
<retain name="download_file">
|
||||
<sectionframe title="Ian's Library">
|
||||
<div class="music-song-list" id="music-list-ianslibrary"></div>
|
||||
</sectionframe>
|
||||
<script>
|
||||
__renderMusicFolder('music-list-ianslibrary', 'ianslibrary', '/assets/musiclink/ianslibrary');
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<retain name="download_file">
|
||||
<sectionframe title="Old Library">
|
||||
<div class="music-song-list" id="music-list-library"></div>
|
||||
</sectionframe>
|
||||
<script>
|
||||
__renderMusicFolder('music-list-library', 'library', '/assets/musiclink/library');
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<retain name="download_file">
|
||||
<sectionframe title="BARANT Audio Experiments">
|
||||
<div class="music-song-list" id="music-list-bae"></div>
|
||||
</sectionframe>
|
||||
<script>
|
||||
__renderMusicFolder('music-list-bae', 'bae', '/assets/musiclink/bae');
|
||||
</script>
|
||||
@@ -0,0 +1,23 @@
|
||||
<sectionframe title="Welcome to BARANT Systems">
|
||||
|
||||
<div style="width: 48%;">
|
||||
<p>We are BARANT Technology Group. Contact us for information on how we can
|
||||
help you with your technical objectives.</p>
|
||||
|
||||
<h1>Modular1 VST Synthesizer</h1>
|
||||
<p>Check out our <a href="/vst">Modular1 VST3
|
||||
Synthesizer</a> If you appreciate the art of modular analog
|
||||
synthesizers then you will really enjoy the Modular1 with all the
|
||||
features of an analog modular synthesizer put into a single VST3
|
||||
instrument. With the added features of polyphony and patches that
|
||||
change instantaneously this synthesizer is truly a powerhouse in the
|
||||
audio toolbox.</p>
|
||||
<a href="/vst"><img src="/assets/modular1.png" style="width: 200px;" align="left"></a>
|
||||
<p>Excellent quality and technical performance provide a performance level
|
||||
instrument for musicians or students who wish to learn sound wave
|
||||
synthesis techniques or for musicians to enable that old analog sound
|
||||
in their DAW recording system..</p>
|
||||
<p>Checkout the product page for more information on the capabilities
|
||||
of the Modular1 synthesizer.</p>
|
||||
</div>
|
||||
</sectionframe>
|
||||
@@ -1,7 +1,29 @@
|
||||
<sectionframe title="MAIN">
|
||||
<if value1="$[SUBPAGE]" value2="" type="eq">
|
||||
<linkbutton page="main" class="submenuitem-active">OVERVIEW</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="main">OVERVIEW</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="music" type="eq">
|
||||
<linkbutton page="main" subpage="music" class="submenuitem-active">MUSIC</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="main" subpage="music">MUSIC</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="library" type="eq">
|
||||
<linkbutton page="main" subpage="library" class="submenuitem-active">MATT'S LIBRARY</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="main" subpage="library">MATT'S LIBRARY</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="ianslibrary" type="eq">
|
||||
<linkbutton page="main" subpage="ianslibrary" class="submenuitem-active">IAN'S LIBRARY</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="main" subpage="ianslibrary">IAN'S LIBRARY</linkbutton><br>
|
||||
</if>
|
||||
</sectionframe>
|
||||
<sectionframe title="QUICK LINKS">
|
||||
<linkbutton page="services">SERVICES</linkbutton><br>
|
||||
<linkbutton page="hosting">HOSTING</linkbutton><br>
|
||||
<linkbutton page="siptrunk">SIP TRUNKING</linkbutton><br>
|
||||
<linkbutton page="services" subpage="hosting">HOSTING</linkbutton><br>
|
||||
<linkbutton page="services" subpage="siptrunking">SIP TRUNKING</linkbutton><br>
|
||||
<linkbutton page="opensource">OPEN SOURCE</linkbutton><br>
|
||||
<linkbutton page="contact">CONTACT</linkbutton>
|
||||
</sectionframe>
|
||||
@@ -2,28 +2,16 @@
|
||||
<title>BARANT Technology Group</title>
|
||||
<contents>
|
||||
<setenv name="_menubar"></setenv>
|
||||
<sectionframe title="Welcome to BARANT Systems">
|
||||
|
||||
<div style="width: 48%;">
|
||||
<p>We are BARANT Technology Group. Contact us for information on how we can
|
||||
help you with your technical objectives.</p>
|
||||
|
||||
<h1>Modular1 VST Synthesizer</h1>
|
||||
<p>Check out our <a href="/vst">Modular1 VST3
|
||||
Synthesizer</a> If you appreciate the art of modular analog
|
||||
synthesizers then you will really enjoy the Modular1 with all the
|
||||
features of an analog modular synthesizer put into a single VST3
|
||||
instrument. With the added features of polyphony and patches that
|
||||
change instantaneously this synthesizer is truly a powerhouse in the
|
||||
audio toolbox.</p>
|
||||
<a href="/vst"><img src="/assets/modular1.png" style="width: 200px;" align="left"></a>
|
||||
<p>Excellent quality and technical performance provide a performance level
|
||||
instrument for musicians or students who wish to learn sound wave
|
||||
synthesis techniques or for musicians to enable that old analog sound
|
||||
in their DAW recording system..</p>
|
||||
<p>Checkout the product page for more information on the capabilities
|
||||
of the Modular1 synthesizer.</p>
|
||||
<div id="main-subpage">
|
||||
<if value1="$[SUBPAGE]" value2="" type="eq">
|
||||
<include file="main-overview.subpage">
|
||||
<else>
|
||||
<try>
|
||||
<include file="main-$[SUBPAGE].subpage">
|
||||
<catch>
|
||||
<p>That page doesn't exist.</p>
|
||||
</try>
|
||||
</if>
|
||||
</div>
|
||||
</sectionframe>
|
||||
</contents>
|
||||
</page>
|
||||
@@ -72,7 +72,7 @@ $[_BODY]
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>BARANT Technology Group</title>
|
||||
<link rel="stylesheet" href="/assets/main.css?v=20260908a">
|
||||
<link rel="stylesheet" href="/assets/main.css?v=20261006a">
|
||||
<link rel="stylesheet" href="/assets/control.css?v=20260902">
|
||||
</head>
|
||||
<body>
|
||||
@@ -88,13 +88,753 @@ $[_BODY]
|
||||
<div class="pageclass">
|
||||
<div class="heading">
|
||||
<div style="display: inline-block; width: 500px;">
|
||||
<a href="https://barant.com"><img style="width: 60px; height: 60px; margin: 10px; background-color: #000; border-radius: 6px; padding: 4px; box-sizing: border-box;" align="left" src="/assets/btglogo.png"></a>
|
||||
<div style="padding-top: 15px;">
|
||||
<div style="left: 80px; color: #c5a45a; font-size: 20pt; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;">BARANT TECHNOLOGY GROUP</div>
|
||||
</div>
|
||||
<a href="https://barant.com"><img style="height: 100px; width: auto; margin: 10px; border-radius: 6px; box-sizing: border-box;" align="left" src="/assets/btglogo.png"></a>
|
||||
</div>
|
||||
<div id="loginmenu" style="float: right; text-align: right; margin-right: 10px; margin-top: 5px;"><include file="login.menu"></div>
|
||||
</div>
|
||||
<div id="globalplayer-band" class="globalplayer-band">
|
||||
<div id="globalplayer-playpause" class="globalplayer-btn" title="Play/Pause" onclick="__playerTogglePause();">
|
||||
<svg id="globalplayer-playicon" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
|
||||
<svg id="globalplayer-pauseicon" viewBox="0 0 24 24" fill="currentColor" style="display:none;"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>
|
||||
</div>
|
||||
<div id="globalplayer-stop" class="globalplayer-btn" title="Stop" onclick="__playerStop();">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12"/></svg>
|
||||
</div>
|
||||
<div id="globalplayer-skip" class="globalplayer-btn" title="Skip" onclick="__playerAdvance();">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M6 5v14l8-7zM16 5h2v14h-2z"/></svg>
|
||||
</div>
|
||||
<div id="globalplayer-title" class="globalplayer-title">
|
||||
<div id="globalplayer-duration" class="globalplayer-duration"></div>
|
||||
<div id="globalplayer-random-indicator" class="globalplayer-random-indicator">RANDOM</div>
|
||||
<div id="globalplayer-title-text" class="globalplayer-title-text">Not Playing</div>
|
||||
<div id="globalplayer-progress" class="globalplayer-progress"><div id="globalplayer-progress-fill" class="globalplayer-progress-fill"></div><div id="globalplayer-progress-handle" class="globalplayer-progress-handle"></div></div>
|
||||
</div>
|
||||
<input type="range" id="globalplayer-volume" class="globalplayer-volume" min="0" max="100" value="<if value1="$[@_player_volume]" value2="" type="eq">100<else>$[@_player_volume]</if>" title="Volume" oninput="__playerSetVolume(this.value);" onchange="__playerPersistVolume(this.value);">
|
||||
<canvas id="globalplayer-eq" class="globalplayer-eq" width="60" height="32"></canvas>
|
||||
<div id="globalplayer-queue-toggle" class="globalplayer-btn globalplayer-btn-text" title="Playlist" onclick="__playerToggleQueue();">RANDOM</div>
|
||||
<audio id="globalaudio" style="display:none;"></audio>
|
||||
</div>
|
||||
<script type="application/json" id="globalplayer-saved-state">$[@_player_state]</script>
|
||||
<div id="globalplayer-queue" class="globalplayer-queue"></div>
|
||||
<script>
|
||||
// Global, persistent music player + playlist queue - lives here (outside
|
||||
// the #content area) specifically so it survives spa.js's per-navigation
|
||||
// content.innerHTML swap: this whole full-page-load branch of
|
||||
// mainpagetemplate.jet only ever renders once per real browser
|
||||
// navigation, never again on a client-side SPA page change (the
|
||||
// fragment branch further below renders none of this) - so this
|
||||
// audio element and the playlist array it drives keep running
|
||||
// uninterrupted across every subsequent in-app page click, exactly
|
||||
// like the request asked for (as long as you do not leave the domain).
|
||||
var __playlist = [];
|
||||
var __currentIndex = -1;
|
||||
var __isIdle = true;
|
||||
var __playToken = 0;
|
||||
// Turned on by clicking RANDOM while nothing is queued, turned back
|
||||
// off by clicking the same button (now showing HALT) - while on, the
|
||||
// queue auto-refills with another random pick instead of going idle
|
||||
// or sitting empty whenever it runs out, rather than that one click
|
||||
// only ever adding a single song.
|
||||
var __autoRandomMode = false;
|
||||
|
||||
// Display-only - the real audio.src below still uses entry.file in
|
||||
// full, extension included, since that is what the server actually
|
||||
// needs to find the right file on disk.
|
||||
function __stripExtension(filename) {
|
||||
var dot = filename.lastIndexOf('.');
|
||||
return dot > 0 ? filename.substring(0, dot) : filename;
|
||||
}
|
||||
|
||||
function __playerLoad(entry) {
|
||||
var audio = document.getElementById('globalaudio');
|
||||
var title = document.getElementById('globalplayer-title-text');
|
||||
document.getElementById('globalplayer-band').classList.add('globalplayer-open');
|
||||
__setProgress(0);
|
||||
document.getElementById('globalplayer-duration').textContent = '0:00';
|
||||
var myToken = ++__playToken;
|
||||
audio.src = entry.path + '/' + entry.file;
|
||||
title.textContent = __stripExtension(entry.file);
|
||||
audio.load();
|
||||
audio.play().catch(function(err) {
|
||||
// Same AbortError race already solved once for the old per-page
|
||||
// player (see the history of main-music.subpage) - a later selection
|
||||
// already owns recovery if it has since bumped __playToken.
|
||||
if (myToken === __playToken) __playerAdvance();
|
||||
});
|
||||
}
|
||||
|
||||
function __goIdle() {
|
||||
var audio = document.getElementById('globalaudio');
|
||||
audio.pause();
|
||||
__isIdle = true;
|
||||
document.getElementById('globalplayer-band').classList.remove('globalplayer-open');
|
||||
document.getElementById('globalplayer-title-text').textContent = 'Not Playing';
|
||||
__setProgress(0);
|
||||
document.getElementById('globalplayer-duration').textContent = '';
|
||||
}
|
||||
|
||||
// The song-picker row stays marked (checkmark + flash) via addToPlaylist
|
||||
// for as long as its entry is actually sitting in __playlist - this
|
||||
// clears that mark once a song is no longer there, whether it finished
|
||||
// naturally or was deleted via the remove button. Matches by data-path/
|
||||
// data-file rather than building a CSS attribute-selector string, since
|
||||
// real filenames can contain quotes/other characters that would need
|
||||
// escaping to use safely in one.
|
||||
function __unmarkSongRow(path, file) {
|
||||
document.querySelectorAll('.music-song-row').forEach(function(row) {
|
||||
if (row.dataset.path === path && row.dataset.file === file) {
|
||||
row.classList.remove('song-queued');
|
||||
row.classList.remove('song-queued-flash');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Shared by __playerAdvance and __removeFromPlaylist - whichever path
|
||||
// the queue became empty through, the same rule applies: auto-random
|
||||
// mode refills it with another pick instead of actually going idle.
|
||||
function __goIdleOrAutoFill() {
|
||||
if (__autoRandomMode) {
|
||||
__isIdle = true;
|
||||
__playRandomSong();
|
||||
} else {
|
||||
__goIdle();
|
||||
}
|
||||
}
|
||||
|
||||
function __playerAdvance() {
|
||||
var finished = __playlist[__currentIndex];
|
||||
if (__currentIndex + 1 < __playlist.length) {
|
||||
__currentIndex++;
|
||||
__playerLoad(__playlist[__currentIndex]);
|
||||
} else {
|
||||
__goIdleOrAutoFill();
|
||||
}
|
||||
if (finished) __unmarkSongRow(finished.path, finished.file);
|
||||
__renderQueue();
|
||||
}
|
||||
|
||||
// Removing a not-yet-played entry just drops it. Removing the
|
||||
// CURRENTLY playing one is treated like a skip: splice it out, then
|
||||
// whatever was queued right behind it has shifted down into this same
|
||||
// index, so loading __playlist[__currentIndex] again (unchanged value,
|
||||
// now pointing at a different entry) picks it up - or goes idle if
|
||||
// that was the last one left. A row for anything already played is
|
||||
// never rendered in the dropdown in the first place (see __renderQueue
|
||||
// - it only shows current-and-later), so there is no "delete history"
|
||||
// case to handle here.
|
||||
function __removeFromPlaylist(index) {
|
||||
var removed = __playlist[index];
|
||||
if (index === __currentIndex) {
|
||||
__playlist.splice(index, 1);
|
||||
if (index < __playlist.length) {
|
||||
__playerLoad(__playlist[__currentIndex]);
|
||||
} else {
|
||||
__goIdleOrAutoFill();
|
||||
}
|
||||
} else if (index > __currentIndex) {
|
||||
__playlist.splice(index, 1);
|
||||
}
|
||||
if (removed) __unmarkSongRow(removed.path, removed.file);
|
||||
__renderQueue();
|
||||
}
|
||||
|
||||
// Only ever called with indices from rows actually rendered in the
|
||||
// dropdown, which (see __renderQueue's own comment) never include the
|
||||
// currently-playing entry - so this only ever reorders the upcoming
|
||||
// portion of the queue, never disturbs __currentIndex itself.
|
||||
function __reorderPlaylist(fromIndex, toIndex) {
|
||||
if (fromIndex === toIndex) return;
|
||||
var item = __playlist.splice(fromIndex, 1)[0];
|
||||
__playlist.splice(toIndex, 0, item);
|
||||
__renderQueue();
|
||||
}
|
||||
|
||||
function __setProgress(ratio) {
|
||||
var pct = (Math.max(0, Math.min(1, ratio)) * 100) + '%';
|
||||
document.getElementById('globalplayer-progress-fill').style.width = pct;
|
||||
document.getElementById('globalplayer-progress-handle').style.left = pct;
|
||||
}
|
||||
|
||||
function __updateTimeDisplay(current, total) {
|
||||
document.getElementById('globalplayer-duration').textContent = __formatTime(current) + ' / ' + __formatTime(total);
|
||||
}
|
||||
|
||||
// Shared with the music/jukebox subpages' own song-picker lists (not
|
||||
// just the playlist dropdown) - a lightweight metadata-only probe so
|
||||
// each row can show its own track length without needing to play it
|
||||
// first.
|
||||
// All duration probes (both this and addToPlaylist's own) funnel
|
||||
// through one strictly-sequential queue - a song list can easily have
|
||||
// 100+ rows, and firing a probe per row all at once was saturating the
|
||||
// browser's per-origin connection limit (6 concurrent, in most
|
||||
// browsers) with background metadata fetches. A real click to actually
|
||||
// play something queues up behind whichever of those happened to grab
|
||||
// a connection first, which is what made selecting a song "not work or
|
||||
// take a long time" - processing one probe at a time, each starting
|
||||
// only once the previous finishes, keeps the other 5 connection slots
|
||||
// free for an actual user-initiated request at all times.
|
||||
var __durationQueue = [];
|
||||
var __durationQueueRunning = false;
|
||||
|
||||
function __queueDurationProbe(path, file, onReady) {
|
||||
__durationQueue.push({path: path, file: file, onReady: onReady});
|
||||
__runDurationQueue();
|
||||
}
|
||||
|
||||
function __runDurationQueue() {
|
||||
if (__durationQueueRunning || __durationQueue.length === 0) return;
|
||||
__durationQueueRunning = true;
|
||||
var item = __durationQueue.shift();
|
||||
var probe = new Audio();
|
||||
probe.preload = 'metadata';
|
||||
function done() {
|
||||
__durationQueueRunning = false;
|
||||
__runDurationQueue();
|
||||
}
|
||||
probe.addEventListener('loadedmetadata', function() {
|
||||
item.onReady(probe.duration);
|
||||
done();
|
||||
});
|
||||
probe.addEventListener('error', done);
|
||||
probe.src = item.path + '/' + item.file;
|
||||
}
|
||||
|
||||
function __loadSongDuration(path, file, el) {
|
||||
if (!el) return;
|
||||
__queueDurationProbe(path, file, function(duration) {
|
||||
el.textContent = __formatTime(duration);
|
||||
});
|
||||
}
|
||||
|
||||
function __formatTime(seconds) {
|
||||
if (!seconds || isNaN(seconds) || !isFinite(seconds)) return '0:00';
|
||||
seconds = Math.floor(seconds);
|
||||
var h = Math.floor(seconds / 3600);
|
||||
var m = Math.floor((seconds % 3600) / 60);
|
||||
var s = seconds % 60;
|
||||
var sStr = (s < 10 ? '0' : '') + s;
|
||||
if (h > 0) {
|
||||
var mStr = (m < 10 ? '0' : '') + m;
|
||||
return h + ':' + mStr + ':' + sStr;
|
||||
}
|
||||
return m + ':' + sStr;
|
||||
}
|
||||
|
||||
function __escapeHtml(s) {
|
||||
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
|
||||
// Builds a music subpage's song list client-side from the fast JSON
|
||||
// listing route (GET /assets/musiclist/{subfolder}), rather than having
|
||||
// the server render one row per file via a directory-loop tag - that
|
||||
// path was genuinely slow for these particular folders (~1200+ files
|
||||
// each), since every literal HTML element inside a Jet loop body costs
|
||||
// real, compounding interpreter overhead per iteration. The container
|
||||
// appears instantly (empty) on navigation; this fills it in shortly
|
||||
// after via one fetch, in small batches via requestAnimationFrame
|
||||
// rather than one giant synchronous DOM write, so the list visibly
|
||||
// populates rather than the page just sitting blank until everything
|
||||
// is ready at once.
|
||||
function __renderMusicFolder(containerId, subfolder, basePath) {
|
||||
var container = document.getElementById(containerId);
|
||||
if (!container) return;
|
||||
fetch('/assets/musiclist/' + subfolder)
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
var files = data.files || [];
|
||||
var i = 0;
|
||||
function appendBatch() {
|
||||
var end = Math.min(i + 100, files.length);
|
||||
for (; i < end; i++) {
|
||||
var file = files[i];
|
||||
var row = document.createElement('div');
|
||||
row.className = 'music-song-row';
|
||||
row.dataset.path = basePath;
|
||||
row.dataset.file = file;
|
||||
var nameSpan = document.createElement('span');
|
||||
nameSpan.className = 'music-song-name';
|
||||
nameSpan.textContent = __stripExtension(file);
|
||||
var durSpan = document.createElement('span');
|
||||
durSpan.className = 'music-song-duration';
|
||||
row.appendChild(nameSpan);
|
||||
row.appendChild(durSpan);
|
||||
row.addEventListener('click', (function(rowEl, path, fname) {
|
||||
return function() { addToPlaylist(rowEl, path, fname); };
|
||||
})(row, basePath, file));
|
||||
container.appendChild(row);
|
||||
__loadSongDuration(basePath, file, durSpan);
|
||||
}
|
||||
if (i < files.length) requestAnimationFrame(appendBatch);
|
||||
}
|
||||
appendBatch();
|
||||
})
|
||||
.catch(function(err) {
|
||||
container.textContent = 'Could not load the song list.';
|
||||
});
|
||||
}
|
||||
|
||||
function __playerSetVolume(val) {
|
||||
document.getElementById('globalaudio').volume = val / 100;
|
||||
}
|
||||
|
||||
// Only persists on change (slider release), not on every input event
|
||||
// while dragging, so dragging does not fire a request per pixel moved.
|
||||
function __playerPersistVolume(val) {
|
||||
fetch(window.location.pathname, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: 'PROCESS=setvolume&volume=' + encodeURIComponent(val)
|
||||
});
|
||||
}
|
||||
|
||||
// While idle (nothing playing, nothing queued) there is nothing for a
|
||||
// playlist dropdown to show, so the same button instead offers to pick
|
||||
// something at random - its label reflects whichever of those two
|
||||
// things it would actually do right now, recomputed any time the open/
|
||||
// closed state or __isIdle changes (see __renderQueue's own call to
|
||||
// this).
|
||||
function __updateQueueButtonLabel() {
|
||||
var btn = document.getElementById('globalplayer-queue-toggle');
|
||||
var queueOpen = document.getElementById('globalplayer-queue').classList.contains('globalplayer-queue-open');
|
||||
if (queueOpen) {
|
||||
btn.textContent = 'CLOSE';
|
||||
} else if (__autoRandomMode) {
|
||||
btn.textContent = 'HALT';
|
||||
} else if (!__hasQueuedSongs()) {
|
||||
btn.textContent = 'RANDOM';
|
||||
} else {
|
||||
btn.textContent = 'PLAYLIST';
|
||||
}
|
||||
document.getElementById('globalplayer-random-indicator').classList.toggle('globalplayer-random-indicator-visible', __autoRandomMode);
|
||||
}
|
||||
|
||||
function __hasQueuedSongs() {
|
||||
return !__isIdle && __currentIndex !== -1 && (__currentIndex + 1 < __playlist.length);
|
||||
}
|
||||
|
||||
function __playerToggleQueue() {
|
||||
// Already in auto-random mode - this button's only job right now is
|
||||
// to turn it back off (does not stop whatever is currently playing,
|
||||
// just stops it from auto-refilling once that finishes).
|
||||
if (__autoRandomMode) {
|
||||
__autoRandomMode = false;
|
||||
__updateQueueButtonLabel();
|
||||
return;
|
||||
}
|
||||
// Nothing queued (whether idle or something is already playing) -
|
||||
// turn auto-random mode on and queue the first pick right away rather
|
||||
// than making this a one-shot "add one song" click.
|
||||
if (!__hasQueuedSongs()) {
|
||||
__autoRandomMode = true;
|
||||
__playRandomSong();
|
||||
return;
|
||||
}
|
||||
document.getElementById('globalplayer-queue').classList.toggle('globalplayer-queue-open');
|
||||
__updateQueueButtonLabel();
|
||||
}
|
||||
|
||||
// Picks from whatever song-picker rows happen to be rendered on the
|
||||
// CURRENT page (music/jukebox's own .music-song-row elements) - there
|
||||
// is no server-side "list all songs" endpoint to fall back on, so this
|
||||
// only has songs to choose from when the page you are actually on has
|
||||
// some. Reuses addToPlaylist exactly as a real click would (same
|
||||
// element, same path/file), so the row's own checkmark/flash feedback
|
||||
// and the queue button's label both update exactly as they would for a
|
||||
// manual click.
|
||||
function __playRandomSong() {
|
||||
var rows = document.querySelectorAll('.music-song-row');
|
||||
if (rows.length === 0) return;
|
||||
var row = rows[Math.floor(Math.random() * rows.length)];
|
||||
addToPlaylist(row, row.dataset.path, row.dataset.file, true);
|
||||
}
|
||||
|
||||
// Shows the current song as the first entry, followed by whatever is
|
||||
// still queued up behind it - not a play history, just now-playing
|
||||
// plus up-next, rebuilt every time the queue or current position changes.
|
||||
// The currently-playing entry is deliberately left out of this list -
|
||||
// it's already shown up in the LCD title/progress bar, so the dropdown
|
||||
// now only ever shows what's queued up NEXT, not what's already
|
||||
// playing.
|
||||
|
||||
// Session persistence - survives a real full-page navigation/reload
|
||||
// the same way the volume slider's own session variable already does
|
||||
// (see setvolume.proc), using one JSON blob (one session variable,
|
||||
// one .proc) rather than several separate ones so the whole player
|
||||
// state saves/restores atomically together.
|
||||
// Runs once, at setup - reads the JSON a real full-page load embedded
|
||||
// server-side (see the script#globalplayer-saved-state tag, rendered
|
||||
// from the same session variable setplayerstate.proc writes) and picks
|
||||
// playback back up from there. A plain text node's content needs none
|
||||
// of the quote-escaping embedding this directly inside a JS string
|
||||
// literal would have required, since real song filenames/paths can
|
||||
// contain characters (quotes, etc.) that would otherwise have to be
|
||||
// escaped correctly to avoid corrupting the surrounding script.
|
||||
function __restoreSavedPlayerState() {
|
||||
var stateEl = document.getElementById('globalplayer-saved-state');
|
||||
if (!stateEl) return;
|
||||
var raw = stateEl.textContent.trim();
|
||||
if (!raw) return;
|
||||
var saved;
|
||||
try {
|
||||
saved = JSON.parse(atob(raw));
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
if (!saved || !saved.playlist || !saved.playlist.length) return;
|
||||
|
||||
__playlist = saved.playlist.map(function(p) { return {path: p.path, file: p.file, duration: null}; });
|
||||
__currentIndex = Math.min(Math.max(0, saved.currentIndex || 0), __playlist.length - 1);
|
||||
__isIdle = false;
|
||||
__autoRandomMode = !!saved.autoRandomMode;
|
||||
|
||||
var entry = __playlist[__currentIndex];
|
||||
var audio = document.getElementById('globalaudio');
|
||||
document.getElementById('globalplayer-band').classList.add('globalplayer-open');
|
||||
document.getElementById('globalplayer-title-text').textContent = __stripExtension(entry.file);
|
||||
audio.src = entry.path + '/' + entry.file;
|
||||
audio.load();
|
||||
|
||||
function onceReady() {
|
||||
audio.removeEventListener('loadedmetadata', onceReady);
|
||||
if (saved.position) audio.currentTime = saved.position;
|
||||
if (saved.playing) {
|
||||
// Browsers block unprompted autoplay without a real user gesture -
|
||||
// if that happens, this just stays loaded and paused at the
|
||||
// restored position instead of erroring, the same tolerance the
|
||||
// normal play()-failure handling elsewhere already has.
|
||||
audio.play().catch(function() {});
|
||||
}
|
||||
}
|
||||
audio.addEventListener('loadedmetadata', onceReady);
|
||||
}
|
||||
|
||||
function __buildPlayerState() {
|
||||
var audio = document.getElementById('globalaudio');
|
||||
return {
|
||||
playlist: __playlist.map(function(p) { return {path: p.path, file: p.file}; }),
|
||||
currentIndex: __currentIndex,
|
||||
position: audio.currentTime || 0,
|
||||
playing: !audio.paused,
|
||||
autoRandomMode: __autoRandomMode
|
||||
};
|
||||
}
|
||||
|
||||
// base64-encoded before it ever reaches the server, not just plain
|
||||
// JSON - the session store is itself JSON-backed (JFile), and a raw
|
||||
// JSON string containing quote characters round-trips back out of
|
||||
// the player-state session variable with its quotes re-escaped - the
|
||||
// text node ends up holding broken, double-escaped JSON rather than
|
||||
// the original. Base64 has no quote characters to collide with that
|
||||
// escaping in the first place, so this sidesteps the whole problem
|
||||
// rather than trying to out-guess exactly how many times to un-escape
|
||||
// it.
|
||||
function __persistPlayerState() {
|
||||
fetch(window.location.pathname, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: 'PROCESS=setplayerstate&state=' + encodeURIComponent(btoa(JSON.stringify(__buildPlayerState())))
|
||||
});
|
||||
}
|
||||
|
||||
function __renderQueue() {
|
||||
var queue = document.getElementById('globalplayer-queue');
|
||||
var html = '';
|
||||
if (!__hasQueuedSongs()) {
|
||||
// Nothing to show either way (idle, or playing with nothing queued
|
||||
// behind it) - leave it empty and force it closed rather than
|
||||
// displaying a placeholder message, matching __playerToggleQueue's
|
||||
// own refusal to open it in this state.
|
||||
queue.classList.remove('globalplayer-queue-open');
|
||||
} else {
|
||||
for (var i = __currentIndex + 1; i < __playlist.length; i++) {
|
||||
var name = __escapeHtml(__stripExtension(__playlist[i].file));
|
||||
var dur = (__playlist[i].duration != null) ? __formatTime(__playlist[i].duration) : '';
|
||||
html += '<div class="globalplayer-queue-item" draggable="true" data-index="' + i + '">'
|
||||
+ '<span class="globalplayer-queue-left">'
|
||||
+ '<span class="globalplayer-queue-handle" title="Drag to reorder"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M4 7h16M4 12h16M4 17h16"/></svg></span>'
|
||||
+ '<span class="globalplayer-queue-name">' + name + '</span>'
|
||||
+ '</span>'
|
||||
+ '<span class="globalplayer-queue-right">'
|
||||
+ '<span class="globalplayer-queue-duration">' + dur + '</span>'
|
||||
+ '<button type="button" class="globalplayer-queue-remove" title="Remove" onclick="__removeFromPlaylist(' + i + ');"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16"/><path d="M9 7V4h6v3"/><path d="M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13"/><path d="M10 11v6M14 11v6"/></svg></button>'
|
||||
+ '</span>'
|
||||
+ '</div>';
|
||||
}
|
||||
}
|
||||
queue.innerHTML = html;
|
||||
__updateQueueButtonLabel();
|
||||
__persistPlayerState();
|
||||
}
|
||||
|
||||
function __playerTogglePause() {
|
||||
if (__isIdle) return;
|
||||
var audio = document.getElementById('globalaudio');
|
||||
if (audio.paused) {
|
||||
audio.play();
|
||||
} else {
|
||||
audio.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// Distinct from pause: pause just halts playback in place with the
|
||||
// band staying open (see __playerTogglePause/the pause listener's own
|
||||
// comment) - stop clears the queue entirely and closes the band, a
|
||||
// genuine "shut the player off" rather than a resumable pause.
|
||||
function __playerStop() {
|
||||
__playlist = [];
|
||||
__currentIndex = -1;
|
||||
__goIdle();
|
||||
__renderQueue();
|
||||
}
|
||||
|
||||
// Shared entry point every music/jukebox subpage calls on a song click -
|
||||
// appends to the queue, and only starts playback immediately if the
|
||||
// queue was otherwise idle (nothing already playing/queued).
|
||||
// isAutoRandom is only ever true when __playRandomSong() itself is the
|
||||
// caller (a manual click on a song-picker row never passes it) -
|
||||
// picking a specific song yourself is a clear signal you want to take
|
||||
// back manual control, so that turns auto-random mode back off rather
|
||||
// than leaving the button stuck on HALT while a real, manually-chosen
|
||||
// entry sits in the queue underneath it.
|
||||
function addToPlaylist(el, path, file, isAutoRandom) {
|
||||
if (!isAutoRandom) __autoRandomMode = false;
|
||||
var entry = {path: path, file: file, duration: null};
|
||||
__playlist.push(entry);
|
||||
// The queue only ever stores path/file - duration is not otherwise
|
||||
// known until something actually plays it, so a lightweight probe
|
||||
// (metadata only, not the full file) fetches just enough to learn it
|
||||
// for the playlist dropdown's own display - shares the same
|
||||
// one-at-a-time queue the song-picker list's own probes use (see
|
||||
// __queueDurationProbe's own comment for why that matters).
|
||||
__queueDurationProbe(path, file, function(duration) {
|
||||
entry.duration = duration;
|
||||
__renderQueue();
|
||||
});
|
||||
if (__isIdle) {
|
||||
__isIdle = false;
|
||||
__currentIndex = __playlist.length - 1;
|
||||
__playerLoad(__playlist[__currentIndex]);
|
||||
}
|
||||
__renderQueue();
|
||||
if (el) {
|
||||
el.classList.add('song-queued');
|
||||
el.classList.remove('song-queued-flash');
|
||||
// Force a reflow so re-adding the flash class restarts the animation
|
||||
// even if this same row was already flashed once before.
|
||||
void el.offsetWidth;
|
||||
el.classList.add('song-queued-flash');
|
||||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
var audio = document.getElementById('globalaudio');
|
||||
var band = document.getElementById('globalplayer-band');
|
||||
var playIcon = document.getElementById('globalplayer-playicon');
|
||||
var pauseIcon = document.getElementById('globalplayer-pauseicon');
|
||||
var eqCanvas = document.getElementById('globalplayer-eq');
|
||||
var progressBar = document.getElementById('globalplayer-progress');
|
||||
|
||||
// Delegated on the queue container itself rather than attached per-row,
|
||||
// since __renderQueue() rebuilds every row's markup via innerHTML on
|
||||
// every change - listeners bound directly to a row would be destroyed
|
||||
// and need re-attaching on every single re-render. The container
|
||||
// element itself is never replaced, only its children, so binding here
|
||||
// once at setup survives any number of re-renders.
|
||||
var queueEl = document.getElementById('globalplayer-queue');
|
||||
var __dragSrcIndex = null;
|
||||
queueEl.addEventListener('dragstart', function(e) {
|
||||
var row = e.target.closest('.globalplayer-queue-item');
|
||||
if (!row || row.dataset.index === undefined) return;
|
||||
__dragSrcIndex = parseInt(row.dataset.index, 10);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
row.classList.add('globalplayer-queue-dragging');
|
||||
});
|
||||
queueEl.addEventListener('dragover', function(e) {
|
||||
var row = e.target.closest('.globalplayer-queue-item');
|
||||
if (!row || row.dataset.index === undefined) return;
|
||||
e.preventDefault();
|
||||
queueEl.querySelectorAll('.globalplayer-queue-dragover').forEach(function(el) {
|
||||
el.classList.remove('globalplayer-queue-dragover');
|
||||
});
|
||||
row.classList.add('globalplayer-queue-dragover');
|
||||
});
|
||||
queueEl.addEventListener('dragleave', function(e) {
|
||||
var row = e.target.closest('.globalplayer-queue-item');
|
||||
if (row) row.classList.remove('globalplayer-queue-dragover');
|
||||
});
|
||||
queueEl.addEventListener('drop', function(e) {
|
||||
var row = e.target.closest('.globalplayer-queue-item');
|
||||
e.preventDefault();
|
||||
if (row && row.dataset.index !== undefined && __dragSrcIndex !== null) {
|
||||
__reorderPlaylist(__dragSrcIndex, parseInt(row.dataset.index, 10));
|
||||
}
|
||||
__dragSrcIndex = null;
|
||||
});
|
||||
queueEl.addEventListener('dragend', function() {
|
||||
queueEl.querySelectorAll('.globalplayer-queue-dragging, .globalplayer-queue-dragover').forEach(function(el) {
|
||||
el.classList.remove('globalplayer-queue-dragging', 'globalplayer-queue-dragover');
|
||||
});
|
||||
__dragSrcIndex = null;
|
||||
});
|
||||
|
||||
// Click-or-drag seeking: setPointerCapture means every subsequent
|
||||
// move/up for this same pointer keeps routing here even once the
|
||||
// cursor leaves the bar's own bounds while still held down - the
|
||||
// standard way a scrubber stays grabbed mid-drag rather than losing
|
||||
// the gesture the moment the mouse strays off the (thin, 8px) bar.
|
||||
function seekFromEvent(e) {
|
||||
if (!audio.duration || isNaN(audio.duration)) return;
|
||||
var rect = progressBar.getBoundingClientRect();
|
||||
var ratio = (e.clientX - rect.left) / rect.width;
|
||||
ratio = Math.max(0, Math.min(1, ratio));
|
||||
audio.currentTime = ratio * audio.duration;
|
||||
__setProgress(ratio);
|
||||
__updateTimeDisplay(audio.currentTime, audio.duration);
|
||||
}
|
||||
progressBar.addEventListener('pointerdown', function(e) {
|
||||
progressBar.classList.add('globalplayer-progress-dragging');
|
||||
progressBar.setPointerCapture(e.pointerId);
|
||||
seekFromEvent(e);
|
||||
});
|
||||
progressBar.addEventListener('pointermove', function(e) {
|
||||
if (progressBar.classList.contains('globalplayer-progress-dragging'))
|
||||
seekFromEvent(e);
|
||||
});
|
||||
progressBar.addEventListener('pointerup', function(e) {
|
||||
progressBar.classList.remove('globalplayer-progress-dragging');
|
||||
progressBar.releasePointerCapture(e.pointerId);
|
||||
});
|
||||
var eqCtx = eqCanvas.getContext('2d');
|
||||
audio.volume = document.getElementById('globalplayer-volume').value / 100;
|
||||
audio.addEventListener('ended', function() { __playerAdvance(); });
|
||||
audio.addEventListener('loadedmetadata', function() {
|
||||
__updateTimeDisplay(audio.currentTime, audio.duration);
|
||||
});
|
||||
var __lastPersistTime = 0;
|
||||
audio.addEventListener('timeupdate', function() {
|
||||
if (!progressBar.classList.contains('globalplayer-progress-dragging') && audio.duration && !isNaN(audio.duration)) {
|
||||
__setProgress(audio.currentTime / audio.duration);
|
||||
__updateTimeDisplay(audio.currentTime, audio.duration);
|
||||
}
|
||||
// Position alone is not worth persisting on every tick (several
|
||||
// times a second) - throttled here rather than through
|
||||
// __renderQueue(), which only runs on actual playlist/track changes,
|
||||
// not on ordinary mid-song progress.
|
||||
var now = Date.now();
|
||||
if (now - __lastPersistTime > 5000) {
|
||||
__lastPersistTime = now;
|
||||
__persistPlayerState();
|
||||
}
|
||||
});
|
||||
|
||||
// Stereo FFT-style bar graph in the band itself. Web Audio requires a
|
||||
// real user gesture before an AudioContext will actually run, which a
|
||||
// play event always is - built lazily here, once, on the first real
|
||||
// play rather than up front at page load. A ChannelSplitter feeds one
|
||||
// AnalyserNode per channel so left and right are genuinely independent
|
||||
// readings, not the same mono data mirrored twice.
|
||||
var audioCtx = null, leftAnalyser = null, rightAnalyser = null;
|
||||
|
||||
function setupAudioAnalysis() {
|
||||
if (audioCtx) return;
|
||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
var source = audioCtx.createMediaElementSource(audio);
|
||||
var splitter = audioCtx.createChannelSplitter(2);
|
||||
leftAnalyser = audioCtx.createAnalyser();
|
||||
rightAnalyser = audioCtx.createAnalyser();
|
||||
leftAnalyser.fftSize = 128;
|
||||
rightAnalyser.fftSize = 128;
|
||||
leftAnalyser.smoothingTimeConstant = 0.7;
|
||||
rightAnalyser.smoothingTimeConstant = 0.7;
|
||||
// createMediaElementSource() reroutes the audio element's own output
|
||||
// through the Web Audio graph exclusively - it no longer reaches
|
||||
// speakers on its own past this point, so this connection to
|
||||
// destination is what keeps playback audible, not optional wiring.
|
||||
source.connect(audioCtx.destination);
|
||||
source.connect(splitter);
|
||||
splitter.connect(leftAnalyser, 0);
|
||||
splitter.connect(rightAnalyser, 1);
|
||||
requestAnimationFrame(drawEQ);
|
||||
}
|
||||
|
||||
// Picks bars on a log scale rather than evenly across the raw bin
|
||||
// range - real music concentrates nearly all of its energy in the
|
||||
// first few linearly-indexed bins, so evenly-spaced bins beyond those
|
||||
// read as flat/empty and the whole graph reads as one solid block
|
||||
// instead of a varied spectrum. Spacing bar selection logarithmically
|
||||
// (the same way a real hardware equalizer's bands are laid out) picks
|
||||
// bins that are far enough apart in the actual data to show real
|
||||
// variation bar to bar.
|
||||
function logBin(i, count, bufferLength) {
|
||||
var t = (i + 1) / count;
|
||||
return Math.max(0, Math.min(bufferLength - 1, Math.floor(Math.pow(bufferLength, t)) - 1));
|
||||
}
|
||||
|
||||
function drawEQ() {
|
||||
requestAnimationFrame(drawEQ);
|
||||
var w = eqCanvas.width, h = eqCanvas.height;
|
||||
eqCtx.clearRect(0, 0, w, h);
|
||||
if (!leftAnalyser || !rightAnalyser || audio.paused) return;
|
||||
var bufferLength = leftAnalyser.frequencyBinCount;
|
||||
var leftData = new Uint8Array(bufferLength);
|
||||
var rightData = new Uint8Array(bufferLength);
|
||||
leftAnalyser.getByteFrequencyData(leftData);
|
||||
rightAnalyser.getByteFrequencyData(rightData);
|
||||
|
||||
// Two separate bar groups, left channel and right channel, each
|
||||
// rising from the bottom with a visible gap between bars and between
|
||||
// the two groups - reads as two independent stereo meters rather
|
||||
// than one shape mirrored around a center line.
|
||||
var barsPerChannel = 5;
|
||||
var gap = 2;
|
||||
var channelWidth = (w - gap) / 2;
|
||||
var barWidth = (channelWidth - gap * (barsPerChannel - 1)) / barsPerChannel;
|
||||
|
||||
eqCtx.fillStyle = '#1a8fc4';
|
||||
for (var i = 0; i < barsPerChannel; i++) {
|
||||
var bin = logBin(i, barsPerChannel, bufferLength);
|
||||
var barH = Math.max(2, (leftData[bin] / 255) * h);
|
||||
eqCtx.fillRect(i * (barWidth + gap), h - barH, barWidth, barH);
|
||||
}
|
||||
for (var i = 0; i < barsPerChannel; i++) {
|
||||
var bin = logBin(i, barsPerChannel, bufferLength);
|
||||
var barH = Math.max(2, (rightData[bin] / 255) * h);
|
||||
eqCtx.fillRect(channelWidth + gap * 2 + i * (barWidth + gap), h - barH, barWidth, barH);
|
||||
}
|
||||
}
|
||||
|
||||
audio.addEventListener('play', function() {
|
||||
playIcon.style.display = 'none';
|
||||
pauseIcon.style.display = '';
|
||||
if (!audioCtx) setupAudioAnalysis();
|
||||
else if (audioCtx.state === 'suspended') audioCtx.resume();
|
||||
__persistPlayerState();
|
||||
});
|
||||
audio.addEventListener('pause', function() {
|
||||
// Deliberately does NOT close the band - that is tied to __isIdle
|
||||
// (see __playerLoad/__goIdle) rather than the raw play/pause events,
|
||||
// so pausing just shows the paused icon with the band, LCD, and
|
||||
// scrubber all staying visible. It used to close here, which made a
|
||||
// plain pause look like the whole player had reset.
|
||||
playIcon.style.display = '';
|
||||
pauseIcon.style.display = 'none';
|
||||
__persistPlayerState();
|
||||
});
|
||||
|
||||
// A regular fetch() made this late in a page's life is not reliably
|
||||
// delivered by the browser - sendBeacon exists specifically to still
|
||||
// get a small POST out as the page is actually going away, so a
|
||||
// reload/tab-close/navigation right after a timeupdate tick does not
|
||||
// lose up to 5 seconds of position progress.
|
||||
window.addEventListener('pagehide', function() {
|
||||
var body = 'PROCESS=setplayerstate&state=' + encodeURIComponent(btoa(JSON.stringify(__buildPlayerState())));
|
||||
navigator.sendBeacon(window.location.pathname, new Blob([body], {type: 'application/x-www-form-urlencoded'}));
|
||||
});
|
||||
|
||||
__restoreSavedPlayerState();
|
||||
__renderQueue();
|
||||
})();
|
||||
</script>
|
||||
<div class="menubar" id="menubar">
|
||||
<include file="menu.bar">
|
||||
</div>
|
||||
@@ -115,6 +855,7 @@ $[_BODY]
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="spa-loading-indicator" class="spa-loading-indicator">Retrieving content...</div>
|
||||
<div class="footer" style="clear: both;">© 1999-2026 BARANT Systems, All Rights Reserved</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -131,7 +872,7 @@ $[_BODY]
|
||||
<div id="filemgr-list"><div id="filemgr-empty">No transfers yet.</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/spa.js?v=20260913a"></script>
|
||||
<script src="/assets/spa.js?v=20261006"></script>
|
||||
<script src="/assets/documents.js?v=20260906a"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
<td style="border-bottom: 1pt solid #bbb; width: 20px;"> </td>
|
||||
<tab page="main"><a href="/main">HOME</a></tab>
|
||||
<tab page="services"><a href="/services">SERVICES</a></tab>
|
||||
<tab page="hosting"><a href="/hosting">HOSTING</a></tab>
|
||||
<tab page="store"><a href="/store/createstore">CREATE STORE</a></tab>
|
||||
<tab page="documents"><a href="/documents">DOCUMENT MGMT</a></tab>
|
||||
<tab page="siptrunk"><a href="/siptrunk">SIP TRUNKING</a></tab>
|
||||
<tab page="vst"><a href="/vst">VST</a></tab>
|
||||
<tab page="wordpress"><a href="/wordpress">WORDPRESS</a></tab>
|
||||
<tab page="opensource"><a href="/opensource">OPEN SOURCE</a></tab>
|
||||
@@ -27,7 +24,9 @@
|
||||
</if>
|
||||
<if value1="$[_login_id]" value2="" type="ne">
|
||||
<tab page="account"><a href="/account">ACCOUNT</a></tab>
|
||||
<if value1="$[_login_type]" value2="admin" type="eq">
|
||||
<tab page="admin"><a href="/admin">ADMIN</a></tab>
|
||||
</if>
|
||||
<else>
|
||||
<tab page="login"><a href="/login">LOGIN</a></tab>
|
||||
</if>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<contents>
|
||||
<script>
|
||||
var index = 0;
|
||||
const paths = [];
|
||||
const songs = [];
|
||||
var paths = [];
|
||||
var songs = [];
|
||||
function onselection(id) {
|
||||
var name = '/get_modular_sample.cgi?id=' + id;
|
||||
var player = document.getElementById('player');
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<page secure="yes" loggedin="no">
|
||||
<title>BAE MUSIC</title>
|
||||
<contents>
|
||||
<script>
|
||||
var index = 0;
|
||||
const paths = [];
|
||||
const songs = [];
|
||||
function onselection(path,selection) {
|
||||
var name = path + '/' + selection;
|
||||
var player = document.getElementById('player');
|
||||
var audio = document.getElementById('audio');
|
||||
var title = document.getElementById('title');
|
||||
player.src = name;
|
||||
title.textContent = selection;
|
||||
audio.load();
|
||||
audio.play();
|
||||
}
|
||||
function selectNext() {
|
||||
var index = Math.floor(Math.random()*songs.length) + 1;
|
||||
onselection(paths[index],songs[index]);
|
||||
}
|
||||
</script>
|
||||
<retain name="download_file">
|
||||
<div style="display: inline-block;">
|
||||
<audio id="audio" controls onended="selectNext();">
|
||||
<source id="player" type="audio/mp3">
|
||||
</audio>
|
||||
</div>
|
||||
<div style="font-size: 20px; display: inline-block;" id="title">Click on a title below</div>
|
||||
<sectionframe title="BARANT Audio Experiments">
|
||||
<div>
|
||||
<whiledir name="file" dir="musiclink/bae">
|
||||
<if expr="left('$[file]',1) != '.' ">
|
||||
<div style="cursor: pointer;" onclick="onselection('musiclink/bae','$[file]');">$[file]</div>
|
||||
<script>
|
||||
paths[index]='musiclink/bae';
|
||||
songs[index++]='$[file]';
|
||||
</script>
|
||||
</if>
|
||||
</whiledir>
|
||||
</div>
|
||||
<script>
|
||||
</script>
|
||||
</sectionframe>
|
||||
|
||||
</contents>
|
||||
</page>
|
||||
@@ -1,7 +1,7 @@
|
||||
<page secure="yes" loggedin="yes">
|
||||
<title>PAY INVOICE</title>
|
||||
<script src="https://sandbox.web.squarecdn.com/v1/square.js></script>
|
||||
<contents>
|
||||
<script src="https://sandbox.web.squarecdn.com/v1/square.js"></script>
|
||||
<sectionframe title="Pay Invoice">
|
||||
<entryform>
|
||||
<sql>select * from invoices where id=$[_invoice_id]</sql>
|
||||
@@ -10,8 +10,8 @@
|
||||
<formdata prompt="Date:" data="$[created]">
|
||||
<formdata prompt="Amount Due:" data="$[amount]">
|
||||
<script>
|
||||
const appId = 'sandbox-sq0idb-GGY04gvAQJAmneJHgn_p8Q';
|
||||
const locationId = 'LEMFWBZPEE9ST';
|
||||
var appId = 'sandbox-sq0idb-GGY04gvAQJAmneJHgn_p8Q';
|
||||
var locationId = 'LEMFWBZPEE9ST';
|
||||
|
||||
async function initializeCard(payments) {
|
||||
const card = await payments.card();
|
||||
@@ -74,7 +74,7 @@
|
||||
statusContainer.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async function () {
|
||||
async function initPayInvoice() {
|
||||
if (!window.Square) {
|
||||
throw new Error('Square.js failed to load properly');
|
||||
}
|
||||
@@ -122,7 +122,12 @@
|
||||
cardButton.addEventListener('click', async function (event) {
|
||||
await handlePaymentMethodSubmission(event, card);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading')
|
||||
document.addEventListener('DOMContentLoaded', initPayInvoice);
|
||||
else
|
||||
initPayInvoice();
|
||||
</script>
|
||||
|
||||
<div id="card-container"></div>
|
||||
|
||||
@@ -8,8 +8,12 @@
|
||||
console.log(">" + this.responseText + "<");
|
||||
if(this.responseText == "OK\n") {
|
||||
document.forms[0].PAGE.value = 'thankyou';
|
||||
document.forms[0].submit();
|
||||
document.forms[0].requestSubmit();
|
||||
} else {
|
||||
var payBtn = document.getElementById('pay');
|
||||
payBtn.disabled = false;
|
||||
var processbanner = document.getElementById('process');
|
||||
processbanner.style.visibility = 'hidden';
|
||||
message.innerText = this.responseText;
|
||||
}
|
||||
};
|
||||
@@ -18,30 +22,46 @@
|
||||
}
|
||||
var card;
|
||||
async function buildForm() {
|
||||
// let payments = Square.payments('sandbox-sq0idb-GGY04gvAQJAmneJHgn_p8Q','LEMFWBZPEE9ST');
|
||||
let payments = Square.payments('sq0idp-V4R4vEferpF9kr7d5x5abQ','LV0MRENX5ED3Z');
|
||||
const card = await payments.card({
|
||||
style: {
|
||||
'.input-container.is-focus': { borderColor: '#006AFF' },
|
||||
'.message-text.is-error': { color: '#BF0020' }
|
||||
input: {
|
||||
backgroundColor: '#1c1c24',
|
||||
color: '#e7e4dc',
|
||||
fontSize: '14px'
|
||||
},
|
||||
'input::placeholder': { color: '#8d8c92' },
|
||||
'.input-container': { borderColor: 'rgba(197, 164, 90, 0.28)' },
|
||||
'.input-container.is-focus': { borderColor: '#c5a45a' },
|
||||
'.input-container.is-error': { borderColor: '#a13a3a' },
|
||||
'.message-text': { color: '#8d8c92' },
|
||||
'.message-text.is-error': { color: '#a13a3a' }
|
||||
}
|
||||
});
|
||||
await card.attach('#card');
|
||||
let button = document.getElementById('pay');
|
||||
button.addEventListener('click', async () => {
|
||||
message.innerText = '';
|
||||
let result = await card.tokenize();
|
||||
if (result.status === 'OK') {
|
||||
button.disabled = true;
|
||||
let processbanner = document.getElementById('process');
|
||||
processbanner.style.visibility = 'visible';
|
||||
processCardForm(result.token);
|
||||
} else {
|
||||
let errorMessage = 'Please check your card details and try again.';
|
||||
if (result.errors && result.errors.length && result.errors[0].message)
|
||||
errorMessage = result.errors[0].message;
|
||||
message.innerText = errorMessage;
|
||||
}
|
||||
});
|
||||
}
|
||||
buildForm();
|
||||
</script>
|
||||
<div>Please enter your payment information:</div>
|
||||
<div id="card" style="background-color: #ddd;width: 300px; padding: 5px;"></div>
|
||||
<div style="padding: 5px;"><button id= "pay" type="button">Pay</button></div>
|
||||
<div id="process" style="background-color: #0f0; border: 2px solid #000; padding:
|
||||
5px; display: block-inline; margin: 10px; visibility: hidden;"> Processing Payment - Please wait... </div>
|
||||
<div id="message" style="color: #f00; margin-top: 20px;"></div>
|
||||
<div class="checkout-pay-wrap">
|
||||
<div class="checkout-pay-label">Card Details</div>
|
||||
<div id="card" class="checkout-card-input"></div>
|
||||
<button id="pay" type="button" class="button checkout-pay-btn">Pay $$[amount]</button>
|
||||
<div id="process" class="checkout-processing">Processing Payment — Please wait…</div>
|
||||
<div id="message" class="checkout-error"></div>
|
||||
</div>
|
||||
@@ -1,3 +1,5 @@
|
||||
<sql>select extensions.id as 'X', extensions.exten as 'Phone Number' from phones.extensions where extensions.user_id=$[@_login_id]</sql>
|
||||
<ifrow>
|
||||
<sectionframe title="Phones">
|
||||
|
||||
<button>
|
||||
@@ -7,7 +9,8 @@
|
||||
<showtable page="request" process="selectrequest" name="request_id" value="X">
|
||||
select extensions.id as 'X',
|
||||
extensions.exten as 'Phone Number'
|
||||
from phones.extensions
|
||||
from phones.extensions where extensions.user_id=$[@_login_id]
|
||||
</showtable>
|
||||
|
||||
</sectionframe>
|
||||
</ifrow>
|
||||
@@ -1,3 +1,3 @@
|
||||
<process>
|
||||
<setenv name="_invoice_id">$[invoice_id]</setenv>
|
||||
<set name="@_invoice_id" value="$[invoice_id]">
|
||||
</process>
|
||||
@@ -0,0 +1,27 @@
|
||||
<set name="_send_invoice_id" value="$[invoice_id]">
|
||||
<if value1="$[_send_invoice_id]" value2="" type="eq">
|
||||
<set name="_send_invoice_id" value="$[@_invoice_id]">
|
||||
</if>
|
||||
<sql>select u.email as email, u.name as name from invoices i join users u on i.user_id=u.id where i.id=$[_send_invoice_id]</sql>
|
||||
<ifrow>
|
||||
<set name="_invoice_email_to" value="$[.email]">
|
||||
<if value1="$[_invoice_email_override]" value2="" type="ne">
|
||||
<set name="_invoice_email_to" value="$[_invoice_email_override]">
|
||||
</if>
|
||||
<set name="_invoice_id" value="$[_send_invoice_id]">
|
||||
<eval name="_invoice_html">
|
||||
<include file="invoice.method">
|
||||
</eval>
|
||||
<eval name="_invoice_email_body">
|
||||
<html>
|
||||
<head></head>
|
||||
<body style="margin: 0; padding: 30px 10px; background: #0a0a0d; font-family: Arial, Helvetica, sans-serif;">
|
||||
$[_invoice_html]
|
||||
<p style="text-align: center; color: #8d8c92; font-size: 11px; margin-top: 20px;">BARANT Technology Group</p>
|
||||
</body>
|
||||
</html>
|
||||
</eval>
|
||||
<eval name="_invoice_smtpsend_discard">
|
||||
<smtpsend config="./email.cfg" user="noreply@barant.com" password="NgCe0RolitzgBKVHz2HKfnTd" to="$[_invoice_email_to]" subject="Your BARANT Technology Group Invoice #$[_send_invoice_id]" html="$[_invoice_email_body]">
|
||||
</eval>
|
||||
</ifrow>
|
||||
Executable → Regular
-5
@@ -1,5 +1,3 @@
|
||||
<page>
|
||||
<title>Document Management</title>
|
||||
<style>
|
||||
.price {display: table-cell;
|
||||
background-color: #fff;
|
||||
@@ -32,7 +30,6 @@
|
||||
#documents-list td a:hover, #documents-list td .documents-action:hover { text-decoration: underline; }
|
||||
#documents-empty { color: var(--bond-text-dim); padding: 10px 0; }
|
||||
</style>
|
||||
<contents>
|
||||
<sectionframe title="Document Management">
|
||||
<h1>Online Document Management</h1>
|
||||
<p>BARANT Technology Group now offers document management storage and
|
||||
@@ -52,5 +49,3 @@ documents for any activity with that account.</p>
|
||||
</sectionframe>
|
||||
<script src="/assets/documents-page.js?v=20260906a"></script>
|
||||
</if>
|
||||
</contents>
|
||||
</page>
|
||||
Executable → Regular
+1
-6
@@ -1,6 +1,3 @@
|
||||
<page>
|
||||
<title>HOSTING</title>
|
||||
<contents>
|
||||
<retain name="sku">
|
||||
<sectionframe title="Virtual Machine Hosting">
|
||||
|
||||
@@ -56,10 +53,8 @@ bandwidth and 50GB storage for voice-mail and recordings. Full root
|
||||
access. Full service support contacts available to maintain your
|
||||
phones and other VoIP devices. </p>
|
||||
<p>$49.95/month</p>
|
||||
<p>See our SIP trunking pricing and DID line options as well for a complete
|
||||
<p>See our <linkbutton page="services" subpage="siptrunking">SIP trunking pricing</linkbutton> and DID line options as well for a complete
|
||||
telephony solution.</p>
|
||||
<hr>
|
||||
</sectionframe>
|
||||
<set name="pagemenu" value="davidarant">
|
||||
</contents>
|
||||
</page>
|
||||
@@ -0,0 +1,45 @@
|
||||
<sectionframe title="Welcome to BARANT Systems">
|
||||
|
||||
<div style="width: 48%;">
|
||||
<p>We are BARANT Technology Group. Contact us for information on how we can
|
||||
help you with your technical objectives.</p>
|
||||
|
||||
<h1>Our Services</h1>
|
||||
<ul>
|
||||
<li>Software architecture and development on many platforms.
|
||||
<ul>
|
||||
<li>40+ years on IBM System/3x, AS/400, i Series and IBM i platform.</li>
|
||||
<li>20+ years .NET Web and Winform application development.</li>
|
||||
<li>10+ Android mobile development.</li>
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>Database architecture and development on many platforms.
|
||||
<ul>
|
||||
<li>DB2/400</li>
|
||||
<li>Oracle</li>
|
||||
<li>MySQL</li>
|
||||
<li>PostgreSQL</li>
|
||||
<li>MSSQL</li>
|
||||
<li>Amazon Aurora</li>
|
||||
<li>Amazon DynamoDB</li>
|
||||
<li>MongoDB</li>
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>Telephony and Call Center Solutions
|
||||
<ul>
|
||||
<li>25+ years in call center development and application integration.</li>
|
||||
<li>15+ years on open source FreePBX development and maintenance.</li>
|
||||
<li>10+ as <linkbutton page="services" subpage="siptrunking">SIP trunk provider</linkbutton> offering very competitive rates.</li>
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>Audio Engineering products and projects
|
||||
<ul>
|
||||
<li>Product offering for VST synthesizers for modular analog simulation.</li>
|
||||
<li>Module development for super clean digitally pure wave harmonics.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</sectionframe>
|
||||
Executable → Regular
-5
@@ -1,5 +1,3 @@
|
||||
<page>
|
||||
<title>SIP Trunking</title>
|
||||
<style>
|
||||
.price {display: table-cell;
|
||||
background-color: #fff;
|
||||
@@ -12,7 +10,6 @@
|
||||
}
|
||||
.number {font-size: 30px;}
|
||||
</style>
|
||||
<contents>
|
||||
<sectionframe title="SIP Trunking">
|
||||
<h1>For PBX Systems</h1>
|
||||
<p>Some of the best prices around for adding trunks to your PBX. We
|
||||
@@ -46,5 +43,3 @@ We can also host a PBX for you as well. Complete functionality
|
||||
utilizing FreePBX can be provided on the internet so you do not need
|
||||
to worry about the hardware. We manage and maintain everything for you.
|
||||
</sectionframe>
|
||||
</contents>
|
||||
</page>
|
||||
@@ -0,0 +1,22 @@
|
||||
<sectionframe title="SERVICES">
|
||||
<if value1="$[SUBPAGE]" value2="" type="eq">
|
||||
<linkbutton page="services" class="submenuitem-active">OVERVIEW</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="services">OVERVIEW</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="hosting" type="eq">
|
||||
<linkbutton page="services" subpage="hosting" class="submenuitem-active">HOSTING</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="services" subpage="hosting">HOSTING</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="siptrunking" type="eq">
|
||||
<linkbutton page="services" subpage="siptrunking" class="submenuitem-active">SIP TRUNKING</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="services" subpage="siptrunking">SIP TRUNKING</linkbutton><br>
|
||||
</if>
|
||||
<if value1="$[SUBPAGE]" value2="documents" type="eq">
|
||||
<linkbutton page="services" subpage="documents" class="submenuitem-active">DOCUMENTS</linkbutton><br>
|
||||
<else>
|
||||
<linkbutton page="services" subpage="documents">DOCUMENTS</linkbutton><br>
|
||||
</if>
|
||||
</sectionframe>
|
||||
@@ -2,50 +2,16 @@
|
||||
<title>BARANT Technology Group</title>
|
||||
<contents>
|
||||
<setenv name="_menubar"></setenv>
|
||||
<sectionframe title="Welcome to BARANT Systems">
|
||||
|
||||
<div style="width: 48%;">
|
||||
<p>We are BARANT Technology Group. Contact us for information on how we can
|
||||
help you with your technical objectives.</p>
|
||||
|
||||
<h1>Our Services</h1>
|
||||
<ul>
|
||||
<li>Software architecture and development on many platforms.
|
||||
<ul>
|
||||
<li>40+ years on IBM System/3x, AS/400, i Series and IBM i platform.</li>
|
||||
<li>20+ years .NET Web and Winform application development.</li>
|
||||
<li>10+ Android mobile development.</li>
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>Database architecture and development on many platforms.
|
||||
<ul>
|
||||
<li>DB2/400</li>
|
||||
<li>Oracle</li>
|
||||
<li>MySQL</li>
|
||||
<li>PostgreSQL</li>
|
||||
<li>MSSQL</li>
|
||||
<li>Amazon Aurora</li>
|
||||
<li>Amazon DynamoDB</li>
|
||||
<li>MongoDB</li>
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>Telephony and Call Center Solutions
|
||||
<ul>
|
||||
<li>25+ years in call center development and application integration.</li>
|
||||
<li>15+ years on open source FreePBX development and maintenance.</li>
|
||||
<li>10+ as SIP trunk provider offering very competitive rates.</li>
|
||||
</ul>
|
||||
</li><br>
|
||||
<li>Audio Engineering products and projects
|
||||
<ul>
|
||||
<li>Product offering for VST synthesizers for modular analog simulation.</li>
|
||||
<li>Module development for super clean digitally pure wave harmonics.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div id="services-subpage">
|
||||
<if value1="$[SUBPAGE]" value2="" type="eq">
|
||||
<include file="services-overview.subpage">
|
||||
<else>
|
||||
<try>
|
||||
<include file="services-$[SUBPAGE].subpage">
|
||||
<catch>
|
||||
<p>That services category doesn't exist.</p>
|
||||
</try>
|
||||
</if>
|
||||
</div>
|
||||
</sectionframe>
|
||||
</contents>
|
||||
</page>
|
||||
@@ -0,0 +1 @@
|
||||
<setenv name="_player_state">$[state]</setenv>
|
||||
@@ -0,0 +1 @@
|
||||
<setenv name="_player_volume">$[volume]</setenv>
|
||||
@@ -1,10 +1,11 @@
|
||||
<process>
|
||||
|
||||
<sql>delete from invoices_detail where invoice_id=$[_invoice_id]</sql>
|
||||
<sql>delete from invoices_detail where invoice_id=$[@_invoice_id]</sql>
|
||||
<for start="0" end="$[linecount]" step="1" name="ix">
|
||||
<sql>insert into invoices_detail (invoice_id,sku,sku_suffix,quantity,description,text,price,total,tax_amount,type)
|
||||
values($[_invoice_id],'$[sku$[ix]]','',$[quantity$[ix]],'$[description$[ix]]','$[textarea$[ix]]',$[price$[ix]],$[total$[ix]],$[tax_amount$[ix]],'$[type$[ix]]')</sql>$[sqlerror]
|
||||
values($[@_invoice_id],'$[sku$[ix]]','',$[quantity$[ix]],'$[description$[ix]]','$[textarea$[ix]]',$[price$[ix]],$[total$[ix]],$[tax_amount$[ix]],'$[type$[ix]]')</sql>$[sqlerror]
|
||||
</for>
|
||||
<sql>update invoices set amount=$[invoice_total] where id=$[_invoice_id]</sql>
|
||||
<setpage name="admin_invoice">
|
||||
<sql>update invoices set amount=$[invoice_total], user_id=$[user_id] where id=$[@_invoice_id]</sql>
|
||||
<setpage name="admin">
|
||||
<set name="SUBPAGE" value="invoice">
|
||||
</process>
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,39 @@
|
||||
CKEditor 4
|
||||
==========
|
||||
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
http://ckeditor.com - See LICENSE.md for license information.
|
||||
|
||||
CKEditor is a text editor to be used inside web pages. It's not a replacement
|
||||
for desktop text editors like Word or OpenOffice, but a component to be used as
|
||||
part of web applications and websites.
|
||||
|
||||
## Documentation
|
||||
|
||||
The full editor documentation is available online at the following address:
|
||||
http://docs.ckeditor.com
|
||||
|
||||
## Installation
|
||||
|
||||
Installing CKEditor is an easy task. Just follow these simple steps:
|
||||
|
||||
1. **Download** the latest version from the CKEditor website:
|
||||
http://ckeditor.com. You should have already completed this step, but be
|
||||
sure you have the very latest version.
|
||||
2. **Extract** (decompress) the downloaded file into the root of your website.
|
||||
|
||||
**Note:** CKEditor is by default installed in the `ckeditor` folder. You can
|
||||
place the files in whichever you want though.
|
||||
|
||||
## Checking Your Installation
|
||||
|
||||
The editor comes with a few sample pages that can be used to verify that
|
||||
installation proceeded properly. Take a look at the `samples` directory.
|
||||
|
||||
To test your installation, just call the following page at your website:
|
||||
|
||||
http://<your site>/<CKEditor installation path>/samples/index.html
|
||||
|
||||
For example:
|
||||
|
||||
http://www.example.com/ckeditor/samples/index.html
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
* For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file was added automatically by CKEditor builder.
|
||||
* You may re-use it at any time to build CKEditor again.
|
||||
*
|
||||
* If you would like to build CKEditor online again
|
||||
* (for example to upgrade), visit one the following links:
|
||||
*
|
||||
* (1) https://ckeditor.com/cke4/builder
|
||||
* Visit online builder to build CKEditor from scratch.
|
||||
*
|
||||
* (2) https://ckeditor.com/cke4/builder/8ff7b71bcccc296bcc3a4a5b82942d17
|
||||
* Visit online builder to build CKEditor, starting with the same setup as before.
|
||||
*
|
||||
* (3) https://ckeditor.com/cke4/builder/download/8ff7b71bcccc296bcc3a4a5b82942d17
|
||||
* Straight download link to the latest version of CKEditor (Optimized) with the same setup as before.
|
||||
*
|
||||
* NOTE:
|
||||
* This file is not used by CKEditor, you may remove it.
|
||||
* Changing this file will not change your CKEditor configuration.
|
||||
*/
|
||||
|
||||
var CKBUILDER_CONFIG = {
|
||||
skin: 'moono-lisa',
|
||||
preset: 'standard',
|
||||
ignore: [
|
||||
'.DS_Store',
|
||||
'.bender',
|
||||
'.editorconfig',
|
||||
'.gitattributes',
|
||||
'.gitignore',
|
||||
'.idea',
|
||||
'.jscsrc',
|
||||
'.jshintignore',
|
||||
'.jshintrc',
|
||||
'.mailmap',
|
||||
'.npm',
|
||||
'.travis.yml',
|
||||
'bender-err.log',
|
||||
'bender-out.log',
|
||||
'bender.ci.js',
|
||||
'bender.js',
|
||||
'dev',
|
||||
'gruntfile.js',
|
||||
'less',
|
||||
'node_modules',
|
||||
'package.json',
|
||||
'tests'
|
||||
],
|
||||
plugins : {
|
||||
'a11yhelp' : 1,
|
||||
'about' : 1,
|
||||
'basicstyles' : 1,
|
||||
'blockquote' : 1,
|
||||
'clipboard' : 1,
|
||||
'contextmenu' : 1,
|
||||
'elementspath' : 1,
|
||||
'enterkey' : 1,
|
||||
'entities' : 1,
|
||||
'filebrowser' : 1,
|
||||
'floatingspace' : 1,
|
||||
'format' : 1,
|
||||
'horizontalrule' : 1,
|
||||
'htmlwriter' : 1,
|
||||
'image' : 1,
|
||||
'indentlist' : 1,
|
||||
'link' : 1,
|
||||
'list' : 1,
|
||||
'magicline' : 1,
|
||||
'maximize' : 1,
|
||||
'pastefromword' : 1,
|
||||
'pastetext' : 1,
|
||||
'removeformat' : 1,
|
||||
'resize' : 1,
|
||||
'scayt' : 1,
|
||||
'showborders' : 1,
|
||||
'sourcearea' : 1,
|
||||
'specialchar' : 1,
|
||||
'stylescombo' : 1,
|
||||
'tab' : 1,
|
||||
'table' : 1,
|
||||
'tableselection' : 1,
|
||||
'tabletools' : 1,
|
||||
'toolbar' : 1,
|
||||
'undo' : 1,
|
||||
'uploadimage' : 1,
|
||||
'wsc' : 1,
|
||||
'wysiwygarea' : 1
|
||||
},
|
||||
languages : {
|
||||
'af' : 1,
|
||||
'ar' : 1,
|
||||
'az' : 1,
|
||||
'bg' : 1,
|
||||
'bn' : 1,
|
||||
'bs' : 1,
|
||||
'ca' : 1,
|
||||
'cs' : 1,
|
||||
'cy' : 1,
|
||||
'da' : 1,
|
||||
'de' : 1,
|
||||
'de-ch' : 1,
|
||||
'el' : 1,
|
||||
'en' : 1,
|
||||
'en-au' : 1,
|
||||
'en-ca' : 1,
|
||||
'en-gb' : 1,
|
||||
'eo' : 1,
|
||||
'es' : 1,
|
||||
'es-mx' : 1,
|
||||
'et' : 1,
|
||||
'eu' : 1,
|
||||
'fa' : 1,
|
||||
'fi' : 1,
|
||||
'fo' : 1,
|
||||
'fr' : 1,
|
||||
'fr-ca' : 1,
|
||||
'gl' : 1,
|
||||
'gu' : 1,
|
||||
'he' : 1,
|
||||
'hi' : 1,
|
||||
'hr' : 1,
|
||||
'hu' : 1,
|
||||
'id' : 1,
|
||||
'is' : 1,
|
||||
'it' : 1,
|
||||
'ja' : 1,
|
||||
'ka' : 1,
|
||||
'km' : 1,
|
||||
'ko' : 1,
|
||||
'ku' : 1,
|
||||
'lt' : 1,
|
||||
'lv' : 1,
|
||||
'mk' : 1,
|
||||
'mn' : 1,
|
||||
'ms' : 1,
|
||||
'nb' : 1,
|
||||
'nl' : 1,
|
||||
'no' : 1,
|
||||
'oc' : 1,
|
||||
'pl' : 1,
|
||||
'pt' : 1,
|
||||
'pt-br' : 1,
|
||||
'ro' : 1,
|
||||
'ru' : 1,
|
||||
'si' : 1,
|
||||
'sk' : 1,
|
||||
'sl' : 1,
|
||||
'sq' : 1,
|
||||
'sr' : 1,
|
||||
'sr-latn' : 1,
|
||||
'sv' : 1,
|
||||
'th' : 1,
|
||||
'tr' : 1,
|
||||
'tt' : 1,
|
||||
'ug' : 1,
|
||||
'uk' : 1,
|
||||
'vi' : 1,
|
||||
'zh' : 1,
|
||||
'zh-cn' : 1
|
||||
}
|
||||
};
|
||||
+1231
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
* For licensing, see https://ckeditor.com/legal/ckeditor-oss-license
|
||||
*/
|
||||
|
||||
CKEDITOR.editorConfig = function( config ) {
|
||||
// Define changes to default configuration here.
|
||||
// For complete reference see:
|
||||
// https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html
|
||||
|
||||
// The toolbar groups arrangement, optimized for two toolbar rows.
|
||||
config.toolbarGroups = [
|
||||
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
|
||||
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
|
||||
{ name: 'links' },
|
||||
{ name: 'insert' },
|
||||
{ name: 'forms' },
|
||||
{ name: 'tools' },
|
||||
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
|
||||
{ name: 'others' },
|
||||
'/',
|
||||
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
|
||||
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
|
||||
{ name: 'styles' },
|
||||
{ name: 'colors' },
|
||||
{ name: 'about' }
|
||||
];
|
||||
|
||||
// Remove some buttons provided by the standard plugins, which are
|
||||
// not needed in the Standard(s) toolbar.
|
||||
config.removeButtons = 'Underline,Subscript,Superscript';
|
||||
|
||||
// Set the most common block elements.
|
||||
config.format_tags = 'p;h1;h2;h3;pre';
|
||||
|
||||
// Simplify the dialog windows.
|
||||
config.removeDialogTabs = 'image:advanced;link:advanced';
|
||||
};
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
*/
|
||||
|
||||
body
|
||||
{
|
||||
/* Font */
|
||||
/* Emoji fonts are added to visualise them nicely in Internet Explorer. */
|
||||
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-size: 12px;
|
||||
|
||||
/* Text color */
|
||||
color: #333;
|
||||
|
||||
/* Remove the background color to make it transparent. */
|
||||
background-color: #fff;
|
||||
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.cke_editable
|
||||
{
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
|
||||
/* Fix for missing scrollbars with RTL texts. (#10488) */
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
blockquote
|
||||
{
|
||||
font-style: italic;
|
||||
font-family: Georgia, Times, "Times New Roman", serif;
|
||||
padding: 2px 0;
|
||||
border-style: solid;
|
||||
border-color: #ccc;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.cke_contents_ltr blockquote
|
||||
{
|
||||
padding-left: 20px;
|
||||
padding-right: 8px;
|
||||
border-left-width: 5px;
|
||||
}
|
||||
|
||||
.cke_contents_rtl blockquote
|
||||
{
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
border-right-width: 5px;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
color: #0782C1;
|
||||
}
|
||||
|
||||
ol,ul,dl
|
||||
{
|
||||
/* IE7: reset rtl list margin. (#7334) */
|
||||
*margin-right: 0px;
|
||||
/* Preserved spaces for list items with text direction different than the list. (#6249,#8049)*/
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6
|
||||
{
|
||||
font-weight: normal;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
border: 0px;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
img.right
|
||||
{
|
||||
border: 1px solid #ccc;
|
||||
float: right;
|
||||
margin-left: 15px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
img.left
|
||||
{
|
||||
border: 1px solid #ccc;
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
white-space: pre-wrap; /* CSS 2.1 */
|
||||
word-wrap: break-word; /* IE7 */
|
||||
-moz-tab-size: 4;
|
||||
tab-size: 4;
|
||||
}
|
||||
|
||||
.marker
|
||||
{
|
||||
background-color: Yellow;
|
||||
}
|
||||
|
||||
span[lang]
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
figure
|
||||
{
|
||||
text-align: center;
|
||||
outline: solid 1px #ccc;
|
||||
background: rgba(0,0,0,0.05);
|
||||
padding: 10px;
|
||||
margin: 10px 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
figure > figcaption
|
||||
{
|
||||
text-align: center;
|
||||
display: block; /* For IE8 */
|
||||
}
|
||||
|
||||
a > img {
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
border: none;
|
||||
outline: 1px solid #0782C1;
|
||||
}
|
||||
|
||||
/* Widget Styles */
|
||||
.code-featured
|
||||
{
|
||||
border: 5px solid red;
|
||||
}
|
||||
|
||||
.math-featured
|
||||
{
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 2px rgba(200, 0, 0, 1);
|
||||
background-color: rgba(255, 0, 0, 0.05);
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.image-clean
|
||||
{
|
||||
border: 0;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.image-clean > figcaption
|
||||
{
|
||||
font-size: .9em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.image-grayscale
|
||||
{
|
||||
background-color: white;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.image-grayscale img, img.image-grayscale
|
||||
{
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.embed-240p
|
||||
{
|
||||
max-width: 426px;
|
||||
max-height: 240px;
|
||||
margin:0 auto;
|
||||
}
|
||||
|
||||
.embed-360p
|
||||
{
|
||||
max-width: 640px;
|
||||
max-height: 360px;
|
||||
margin:0 auto;
|
||||
}
|
||||
|
||||
.embed-480p
|
||||
{
|
||||
max-width: 854px;
|
||||
max-height: 480px;
|
||||
margin:0 auto;
|
||||
}
|
||||
|
||||
.embed-720p
|
||||
{
|
||||
max-width: 1280px;
|
||||
max-height: 720px;
|
||||
margin:0 auto;
|
||||
}
|
||||
|
||||
.embed-1080p
|
||||
{
|
||||
max-width: 1920px;
|
||||
max-height: 1080px;
|
||||
margin:0 auto;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['af']={"editor":"Woordverwerker","editorPanel":"Woordverwerkerpaneel","common":{"editorHelp":"Druk op ALT 0 vir hulp","browseServer":"Blaai op bediener","url":"URL","protocol":"Protokol","upload":"Oplaai","uploadSubmit":"Stuur aan die bediener","image":"Beeld","flash":"Flash","form":"Vorm","checkbox":"Merkhokkie","radio":"Radioknoppie","textField":"Teksveld","textarea":"Teksarea","hiddenField":"Versteekteveld","button":"Knop","select":"Keuseveld","imageButton":"Beeldknop","notSet":"<geen instelling>","id":"Id","name":"Naam","langDir":"Skryfrigting","langDirLtr":"Links na regs (LTR)","langDirRtl":"Regs na links (RTL)","langCode":"Taalkode","longDescr":"Lang beskrywing URL","cssClass":"CSS klasse","advisoryTitle":"Aanbevole titel","cssStyle":"Styl","ok":"OK","cancel":"Kanselleer","close":"Sluit","preview":"Voorbeeld","resize":"Skalierung","generalTab":"Algemeen","advancedTab":"Gevorderd","validateNumberFailed":"Hierdie waarde is nie 'n nommer nie.","confirmNewPage":"Alle wysiginge sal verlore gaan. Is jy seker dat jy 'n nuwe bladsy wil laai?","confirmCancel":"Sommige opsies is gewysig. Is jy seker dat jy hierdie dialoogvenster wil sluit?","options":"Opsies","target":"Teiken","targetNew":"Nuwe venster (_blank)","targetTop":"Boonste venster (_top)","targetSelf":"Selfde venster (_self)","targetParent":"Oorspronklike venster (_parent)","langDirLTR":"Links na Regs (LTR)","langDirRTL":"Regs na Links (RTL)","styles":"Styl","cssClasses":"CSS klasse","width":"Breedte","height":"Hoogte","align":"Orienteerung","left":"Links","right":"Regs","center":"Middel","justify":"Eweredig","alignLeft":"Links oplyn","alignRight":"Regs oplyn","alignCenter":"Middel oplyn","alignTop":"Bo","alignMiddle":"Middel","alignBottom":"Onder","alignNone":"Geen","invalidValue":"Ongeldige waarde","invalidHeight":"Hoogte moet 'n getal wees","invalidWidth":"Breedte moet 'n getal wees.","invalidLength":"Die waarde vir die veld \"%1\" moet 'n posetiewe nommer wees met of sonder die meeteenheid (%2).","invalidCssLength":"Die waarde vir die \"%1\" veld moet 'n posetiewe getal wees met of sonder 'n geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","invalidHtmlLength":"Die waarde vir die \"%1\" veld moet 'n posetiewe getal wees met of sonder 'n geldige HTML eenheid (px of %).","invalidInlineStyle":"Ongeldige CSS. Formaat is een of meer sleutel-wert paare, \"naam : wert\" met kommapunte gesky.","cssLengthTooltip":"Voeg 'n getal wert in pixel in, of 'n waarde met geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","unavailable":"%1<span class=\"cke_accessibility\">, nie beskikbaar nie</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Skuif","17":"Ctrl","18":"Alt","32":"Spasie","35":"Einde","36":"Tuis","46":"Verwyder","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Bevel"},"keyboardShortcut":"Sleutel kombenasie","optionDefault":"Verstek"},"about":{"copy":"Kopiereg © $1. Alle regte voorbehou.","dlgTitle":"Meer oor CKEditor 4","moreInfo":"Vir lisensie-informasie, besoek asb. ons webwerf:"},"basicstyles":{"bold":"Vet","italic":"Skuins","strike":"Deurgestreep","subscript":"Onderskrif","superscript":"Bo-skrif","underline":"Onderstreep"},"blockquote":{"toolbar":"Sitaatblok"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Verklein werkbalk","toolbarExpand":"Vergroot werkbalk","toolbarGroups":{"document":"Dokument","clipboard":"Knipbord/Undo","editing":"Verander","forms":"Vorms","basicstyles":"Eenvoudige Styl","paragraph":"Paragraaf","links":"Skakels","insert":"Toevoeg","styles":"Style","colors":"Kleure","tools":"Gereedskap"},"toolbars":"Werkbalke"},"clipboard":{"copy":"Kopiëer","copyError":"U leser se sekuriteitsinstelling belet die kopiëringsaksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+C).","cut":"Uitsnei","cutError":"U leser se sekuriteitsinstelling belet die outomatiese uitsnei-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).","paste":"Byvoeg","pasteNotification":"Druk %1 om by te voeg. You leser ondersteun nie die toolbar knoppie of inoud kieslysie opsie nie. ","pasteArea":"Area byvoeg","pasteMsg":"Voeg jou inhoud in die gebied onder by en druk OK"},"contextmenu":{"options":"Konteks Spyskaart-opsies"},"elementspath":{"eleLabel":"Elemente-pad","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError":"Upload URL is not defined.","responseError":"Incorrect server response."},"format":{"label":"Opmaak","panelTitle":"OpmLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['ar']={"editor":"محرر النص الغني","editorPanel":"لائحة محرر النص المنسق","common":{"editorHelp":"إضغط على ALT + 0 للحصول على المساعدة.","browseServer":"تصفح","url":"الرابط","protocol":"البروتوكول","upload":"رفع","uploadSubmit":"أرسل","image":"صورة","flash":"فلاش","form":"نموذج","checkbox":"خانة إختيار","radio":"زر اختيار","textField":"مربع نص","textarea":"مساحة نصية","hiddenField":"إدراج حقل خفي","button":"زر ضغط","select":"اختار","imageButton":"زر صورة","notSet":"<بدون تحديد>","id":"الرقم","name":"إسم","langDir":"إتجاه النص","langDirLtr":"اليسار لليمين (LTR)","langDirRtl":"اليمين لليسار (RTL)","langCode":"رمز اللغة","longDescr":"الوصف التفصيلى","cssClass":"فئات التنسيق","advisoryTitle":"عنوان التقرير","cssStyle":"نمط","ok":"موافق","cancel":"إلغاء الأمر","close":"أغلق","preview":"استعراض","resize":"تغيير الحجم","generalTab":"عام","advancedTab":"متقدم","validateNumberFailed":"لايوجد نتيجة","confirmNewPage":"ستفقد أي متغييرات اذا لم تقم بحفظها اولا. هل أنت متأكد أنك تريد صفحة جديدة؟","confirmCancel":"بعض الخيارات قد تغيرت. هل أنت متأكد من إغلاق مربع النص؟","options":"خيارات","target":"هدف الرابط","targetNew":"نافذة جديدة","targetTop":"النافذة الأعلى","targetSelf":"داخل النافذة","targetParent":"النافذة الأم","langDirLTR":"اليسار لليمين (LTR)","langDirRTL":"اليمين لليسار (RTL)","styles":"نمط","cssClasses":"فئات التنسيق","width":"العرض","height":"الإرتفاع","align":"محاذاة","left":"يسار","right":"يمين","center":"وسط","justify":"ضبط","alignLeft":"محاذاة إلى اليسار","alignRight":"محاذاة إلى اليمين","alignCenter":"Align Center","alignTop":"أعلى","alignMiddle":"وسط","alignBottom":"أسفل","alignNone":"None","invalidValue":"قيمة غير مفبولة.","invalidHeight":"الارتفاع يجب أن يكون عدداً.","invalidWidth":"العرض يجب أن يكون عدداً.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"قيمة الخانة المخصصة لـ \"%1\" يجب أن تكون رقما موجبا، باستخدام أو من غير استخدام وحدة CSS قياس مقبولة (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"قيمة الخانة المخصصة لـ \"%1\" يجب أن تكون رقما موجبا، باستخدام أو من غير استخدام وحدة HTML قياس مقبولة (px or %).","invalidInlineStyle":"قيمة الخانة المخصصة لـ Inline Style يجب أن تختوي على مجموع واحد أو أكثر بالشكل التالي: \"name : value\", مفصولة بفاصلة منقزطة.","cssLengthTooltip":"أدخل رقما للقيمة بالبكسل أو رقما بوحدة CSS مقبولة (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, غير متاح</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"حقوق النشر © $1. جميع الحقوق محفوظة.","dlgTitle":"عن CKEditor","moreInfo":"للحصول على معلومات الترخيص ، يرجى زيارة موقعنا:"},"basicstyles":{"bold":"عريض","italic":"مائل","strike":"يتوسطه خط","subscript":"منخفض","superscript":"مرتفع","underline":"تسطير"},"blockquote":{"toolbar":"اقتباس"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"تقليص شريط الأدوت","toolbarExpand":"تمديد شريط الأدوات","toolbarGroups":{"document":"مستند","clipboard":"الحافظة/الرجوع","editing":"تحرير","forms":"نماذج","basicstyles":"نمط بسيط","paragraph":"فقرة","links":"روابط","insert":"إدراج","styles":"أنماط","colors":"ألوان","tools":"أدوات"},"toolbars":"أشرطة أدوات المحرر"},"clipboard":{"copy":"نسخ","copyError":"الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع عمليات النسخ التلقائي.Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['az']={"editor":"Mətn Redaktoru","editorPanel":"Mətn Redaktorun Paneli","common":{"editorHelp":"Yardım üçün ALT 0 düymələrini basın","browseServer":"Fayların siyahı","url":"URL","protocol":"Protokol","upload":"Serverə yüklə","uploadSubmit":"Göndər","image":"Şəkil","flash":"Flash","form":"Forma","checkbox":"Çekboks","radio":"Radio düyməsi","textField":"Mətn xanası","textarea":"Mətn","hiddenField":"Gizli xana","button":"Düymə","select":"Opsiyaların seçilməsi","imageButton":"Şəkil tipli düymə","notSet":"<seçilməmiş>","id":"Id","name":"Ad","langDir":"Yaziların istiqaməti","langDirLtr":"Soldan sağa (LTR)","langDirRtl":"Sağdan sola (RTL)","langCode":"Dilin kodu","longDescr":"URL-ın ətraflı izahı","cssClass":"CSS klassları","advisoryTitle":"Başlıq","cssStyle":"CSS","ok":"Tədbiq et","cancel":"İmtina et","close":"Bağla","preview":"Baxış","resize":"Eni dəyiş","generalTab":"Əsas","advancedTab":"Əlavə","validateNumberFailed":"Rəqəm deyil.","confirmNewPage":"Yadda saxlanılmamış dəyişikliklər itiriləcək. Davam etmək istədiyinizə əminsinizmi?","confirmCancel":"Dəyişikliklər edilib. Pəncərəni bağlamaq istəyirsizə əminsinizmi?","options":"Seçimlər","target":"Hədəf çərçivə","targetNew":"Yeni pəncərə (_blank)","targetTop":"Əsas pəncərə (_top)","targetSelf":"Carı pəncərə (_self)","targetParent":"Ana pəncərə (_parent)","langDirLTR":"Soldan sağa (LTR)","langDirRTL":"Sağdan sola (RTL)","styles":"Üslub","cssClasses":"Üslub klası","width":"En","height":"Uzunluq","align":"Yerləşmə","left":"Sol","right":"Sağ","center":"Mərkəz","justify":"Eninə görə","alignLeft":"Soldan düzləndir","alignRight":"Sağdan düzləndir","alignCenter":"Align Center","alignTop":"Yuxarı","alignMiddle":"Orta","alignBottom":"Aşağı","alignNone":"Yoxdur","invalidValue":"Yanlışdır.","invalidHeight":"Hündürlük rəqəm olmalıdır.","invalidWidth":"En rəqəm olmalıdır.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"\"%1\" xanasında göstərilən məzmun tam və müsbət olmalıdır, CSS-də olan ölçü vahidlərin (px, %, in, cm, mm, em, ex, pt, or pc) istifadısinə icazə verilir.","invalidHtmlLength":"\"%1\" xanasında göstərilən məzmun tam və müsbət olmalıdır HTML-də olan ölçü vahidlərin (px və ya %) istifadısinə icazə verilir.","invalidInlineStyle":"Teq içində olan üslub \"ad : məzmun\" şəklidə, nöqtə-verqül işarəsi ilə bitməlidir","cssLengthTooltip":"Piksel sayı və ya digər CSS ölçü vahidləri (px, %, in, cm, mm, em, ex, pt, or pc) daxil edin.","unavailable":"%1<span class=\"cke_accessibility\">, mövcud deyil</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Boşluq","35":"Son","36":"Evə","46":"Sil","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Əmr"},"keyboardShortcut":"Qısayol düymələri","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Bütün hüquqlar qorunur.","dlgTitle":"CKEditor haqqında","moreInfo":"Lisenziya informasiyası üçün zəhmət olmasa saytımızı ziyarət edin:"},"basicstyles":{"bold":"Qalın","italic":"Kursiv","strike":"Üstüxətli","subscript":"Aşağı indeks","superscript":"Yuxarı indeks","underline":"Altdan xətt"},"blockquote":{"toolbar":"Sitat bloku"},"notification":{"closed":"Xəbərdarlıq pəncərəsi bağlanıb"},"toolbar":{"toolbarCollapse":"Paneli gizlət","toolbarExpand":"Paneli göstər","toolbarGroups":{"document":"Mətn","clipboard":"Mübadilə buferi/İmtina et","editing":"Redaktə edilməsi","forms":"Formalar","basicstyles":"Əsas üslublar","paragraph":"Abzas","links":"Link","insert":"Əlavə et","styles":"Üslublar","colors":"Rənqlər","tools":"Alətləri"},"toolbars":"Redaktorun panelləri"},"clipboard":{"copy":"Köçür","copyError":"Avtomatik köçürülməsi mümkün deyil. Ctrl+C basın.","cut":"Kəs","cutError":"Avtomatik kəsmə mümkün deyil. Ctrl+X basın.","paste":"Əlavə et","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Əlavə əməliyyatlar"},"elementspath":{"eleLabel":"Elementin izləri","eleTitle":"%1 element"},"filetools":{"loadError":"Faylını oxumaq mümkün deyil","networkError":"Xəta baş verdi.","httpError404":"Serverə göndərilməsinin zamanı xəta baş verdi (404 - fayl tapılmayıb)","httpError403":"Serverə göndərilməsinin zamanı xəta baş verdi (403 - gadağandır)","httpError":"Serverə göndərLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['bg']={"editor":"Редактор за форматиран текст","editorPanel":"Панел на текстовия редактор","common":{"editorHelp":"натиснете ALT+0 за помощ","browseServer":"Избор от сървъра","url":"URL адрес","protocol":"Протокол","upload":"Качване","uploadSubmit":"Изпращане към сървъра","image":"Изображение","flash":"Флаш","form":"Форма","checkbox":"Поле за избор","radio":"Радио бутон","textField":"Текстово поле","textarea":"Текстова зона","hiddenField":"Скрито поле","button":"Бутон","select":"Поле за избор","imageButton":"Бутон за изображение","notSet":"<не е избрано>","id":"ID","name":"Име","langDir":"Посока на езика","langDirLtr":"От ляво надясно (LTR)","langDirRtl":"От дясно наляво (RTL)","langCode":"Код на езика","longDescr":"Уеб адрес за дълго описание","cssClass":"Класове за CSS","advisoryTitle":"Заглавие","cssStyle":"Стил","ok":"ОК","cancel":"Отказ","close":"Затвори","preview":"Преглед","resize":"Влачете за да оразмерите","generalTab":"Общи","advancedTab":"Разширено","validateNumberFailed":"Тази стойност не е число","confirmNewPage":"Всички незапазени промени ще бъдат изгубени. Сигурни ли сте, че желаете да заредите нова страница?","confirmCancel":"Някои от опциите са променени. Сигурни ли сте, че желаете да затворите прозореца?","options":"Опции","target":"Цел","targetNew":"Нов прозорец (_blank)","targetTop":"Най-горният прозорец (_top)","targetSelf":"Текущият прозорец (_self)","targetParent":"Горният прозорец (_parent)","langDirLTR":"От ляво надясно (LTR)","langDirRTL":"От дясно наляво (RTL)","styles":"Стил","cssClasses":"Класове за CSS","width":"Ширина","height":"Височина","align":"Подравняване","left":"Ляво","right":"Дясно","center":"Център","justify":"Двустранно","alignLeft":"Подравни ляво","alignRight":"Подравни дясно","alignCenter":"Подравни център","alignTop":"Горе","alignMiddle":"По средата","alignBottom":"Долу","alignNone":"Без подравняване","invalidValue":"Невалидна стойност.","invalidHeight":"Височината трябва да е число.","invalidWidth":"Ширина трябва да е число.","invalidLength":"Стойността на полето \"%1\" трябва да е положително число с или без валидна мерна единица (%2).","invalidCssLength":"Стойността на полето \"%1\" трябва да е положително число с или без валидна CSS мерна единица (px, %, in, cm, mm, em, ex, pt, или pc).","invalidHtmlLength":"Стойността на полето \"%1\" трябва да е положително число с или без валидна HTML мерна единица (px или %).","invalidInlineStyle":"Стойността на стилa трябва да съдържат една или повече двойки във формат \"name : value\", разделени с двоеточие.","cssLengthTooltip":"Въведете числена стойност в пиксели или друга валидна CSS единица (px, %, in, cm, mm, em, ex, pt, или pc).","unavailable":"%1<span class=\"cke_accessibility\">, недостъпно</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Клавишна комбинация","optionDefault":"По подразбиране"},"about":{"copy":"Авторско право © $1. Всички права запазени.","dlgTitle":"Относно CKEditor 4","moreInfo":"За лицензионна информация моля посетете сайта ни:"},"basicstyles":{"bold":"Удебелен","italic":"Наклонен","strike":"Зачертан текст","subscript":"Долен индекс","superscript":"Горен индекс","underline":"Подчертан"},"blockquote":{"toolbar":"Блок за цитLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['bn']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"ব্রাউজ সার্ভার","url":"URL","protocol":"প্রোটোকল","upload":"আপলোড","uploadSubmit":"ইহাকে সার্ভারে প্রেরন কর","image":"ছবির লেবেল যুক্ত কর","flash":"ফ্লাশ লেবেল যুক্ত কর","form":"ফর্ম","checkbox":"চেক বাক্স","radio":"রেডিও বাটন","textField":"টেক্সট ফীল্ড","textarea":"টেক্সট এরিয়া","hiddenField":"গুপ্ত ফীল্ড","button":"বাটন","select":"বাছাই ফীল্ড","imageButton":"ছবির বাটন","notSet":"<সেট নেই>","id":"আইডি","name":"নাম","langDir":"ভাষা লেখার দিক","langDirLtr":"বাম থেকে ডান (LTR)","langDirRtl":"ডান থেকে বাম (RTL)","langCode":"ভাষা কোড","longDescr":"URL এর লম্বা বর্ণনা","cssClass":"স্টাইল-শীট ক্লাস","advisoryTitle":"পরামর্শ শীর্ষক","cssStyle":"স্টাইল","ok":"ওকে","cancel":"বাতিল","close":"Close","preview":"প্রিভিউ","resize":"Resize","generalTab":"General","advancedTab":"এডভান্সড","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"টার্গেট","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"বাম থেকে ডান (LTR)","langDirRTL":"ডান থেকে বাম (RTL)","styles":"স্টাইল","cssClasses":"স্টাইল-শীট ক্লাস","width":"প্রস্থ","height":"দৈর্ঘ্য","align":"এলাইন","left":"বামে","right":"ডানে","center":"মাঝখানে","justify":"ব্লক জাস্টিফাই","alignLeft":"বা দিকে ঘেঁষা","alignRight":"ডান দিকে ঘেঁষা","alignCenter":"Align Center","alignTop":"উপর","alignMiddle":"মধ্য","alignBottom":"নীচে","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"বোল্ড","italic":"বাঁকা","strike":"স্ট্রাইক থ্রু","subscript":"অধোলেখ","superscript":"অভিলেখ","underline":"আন্ডারলাইন"},"blockquote":{"toolbar":"Block Quote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"কপি","copyError":"আপনার ব্রাউজারের নিরাপত্তা সেটিংসমূহ এডিটরকLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['bs']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protokol","upload":"Šalji","uploadSubmit":"Šalji na server","image":"Slika","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<nije podešeno>","id":"Id","name":"Naziv","langDir":"Smjer pisanja","langDirLtr":"S lijeva na desno (LTR)","langDirRtl":"S desna na lijevo (RTL)","langCode":"Jezièni kôd","longDescr":"Dugaèki opis URL-a","cssClass":"Klase CSS stilova","advisoryTitle":"Advisory title","cssStyle":"Stil","ok":"OK","cancel":"Odustani","close":"Close","preview":"Prikaži","resize":"Resize","generalTab":"General","advancedTab":"Naprednije","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Prozor","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"S lijeva na desno (LTR)","langDirRTL":"S desna na lijevo (RTL)","styles":"Stil","cssClasses":"Klase CSS stilova","width":"Širina","height":"Visina","align":"Poravnanje","left":"Lijevo","right":"Desno","center":"Centar","justify":"Puno poravnanje","alignLeft":"Lijevo poravnanje","alignRight":"Desno poravnanje","alignCenter":"Align Center","alignTop":"Vrh","alignMiddle":"Sredina","alignBottom":"Dno","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"Boldiraj","italic":"Ukosi","strike":"Precrtaj","subscript":"Subscript","superscript":"Superscript","underline":"Podvuci"},"blockquote":{"toolbar":"Block Quote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"Kopiraj","copyError":"Sigurnosne postavke Vašeg pretraživaèa ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tastaturi (Ctrl/Cmd+C).","cut":"Izreži","cutError":"Sigurnosne postavke vašeg pretraživaèa ne dozvoljavaju operacije automatskog rezanja. Molimo koristite kraticu na tastaturi (Ctrl/Cmd+X).","paste":"Zalijepi","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload
Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['ca']={"editor":"Editor de text enriquit","editorPanel":"Panell de l'editor de text enriquit","common":{"editorHelp":"Premeu ALT 0 per ajuda","browseServer":"Veure servidor","url":"URL","protocol":"Protocol","upload":"Puja","uploadSubmit":"Envia-la al servidor","image":"Imatge","flash":"Flash","form":"Formulari","checkbox":"Casella de verificació","radio":"Botó d'opció","textField":"Camp de text","textarea":"Àrea de text","hiddenField":"Camp ocult","button":"Botó","select":"Camp de selecció","imageButton":"Botó d'imatge","notSet":"<no definit>","id":"Id","name":"Nom","langDir":"Direcció de l'idioma","langDirLtr":"D'esquerra a dreta (LTR)","langDirRtl":"De dreta a esquerra (RTL)","langCode":"Codi d'idioma","longDescr":"Descripció llarga de la URL","cssClass":"Classes del full d'estil","advisoryTitle":"Títol consultiu","cssStyle":"Estil","ok":"D'acord","cancel":"Cancel·la","close":"Tanca","preview":"Previsualitza","resize":"Arrossegueu per redimensionar","generalTab":"General","advancedTab":"Avançat","validateNumberFailed":"Aquest valor no és un número.","confirmNewPage":"Els canvis en aquest contingut que no es desin es perdran. Esteu segur que voleu carregar una pàgina nova?","confirmCancel":"Algunes opcions s'han canviat. Esteu segur que voleu tancar el quadre de diàleg?","options":"Opcions","target":"Destí","targetNew":"Nova finestra (_blank)","targetTop":"Finestra superior (_top)","targetSelf":"Mateixa finestra (_self)","targetParent":"Finestra pare (_parent)","langDirLTR":"D'esquerra a dreta (LTR)","langDirRTL":"De dreta a esquerra (RTL)","styles":"Estil","cssClasses":"Classes del full d'estil","width":"Amplada","height":"Alçada","align":"Alineació","left":"Ajusta a l'esquerra","right":"Ajusta a la dreta","center":"Centre","justify":"Justificat","alignLeft":"Alinea a l'esquerra","alignRight":"Alinea a la dreta","alignCenter":"Align Center","alignTop":"Superior","alignMiddle":"Centre","alignBottom":"Inferior","alignNone":"Cap","invalidValue":"Valor no vàlid.","invalidHeight":"L'alçada ha de ser un número.","invalidWidth":"L'amplada ha de ser un número.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"El valor especificat per als \"%1\" camps ha de ser un número positiu amb o sense unitat de mesura vàlida de CSS (px, %, in, cm, mm, em, ex, pt o pc).","invalidHtmlLength":"El valor especificat per als \"%1\" camps ha de ser un número positiu amb o sense unitat de mesura vàlida d'HTML (px o %).","invalidInlineStyle":"El valor especificat per l'estil en línia ha de constar d'una o més tuples amb el format \"name: value\", separats per punt i coma.","cssLengthTooltip":"Introduïu un número per un valor en píxels o un número amb una unitat vàlida de CSS (px, %, in, cm, mm, em, ex, pt o pc).","unavailable":"%1<span class=\"cke_accessibility\">, no disponible</span>","keyboard":{"8":"Retrocés","13":"Intro","16":"Majúscules","17":"Ctrl","18":"Alt","32":"Space","35":"Fi","36":"Inici","46":"Eliminar","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Tots els drets reservats.","dlgTitle":"Quant al CKEditor 4","moreInfo":"Per informació sobre llicències visiteu el nostre lloc web:"},"basicstyles":{"bold":"Negreta","italic":"Cursiva","strike":"Ratllat","subscript":"Subíndex","superscript":"Superíndex","underline":"Subratllat"},"blockquote":{"toolbar":"Bloc de cita"},"notification":{"closed":"Notificació tancada."},"toolbar":{"toolbarCollapse":"Redueix la barra d'eines","toolbarExpand":"Amplia la barra d'eines","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor de barra d'eines"},"clipboard":{"copy":"Copiar","copyError":"La configuració de seguretat del vostre navegador no permet executar automàticament les operacions de copiar. Si us plau, utilitzeu el teclat (Ctrl/Cmd+C).","cut":"Retallar","cutError":"La configuració de seguretat del vostre navegador no permet executar automàticament les operacions de retallar. Si us plau, utilitzeu el teclat (Ctrl/Cmd+X).","paste":"Enganxar","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Àrea d'enganxat","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Opcions del menú contextual"},"elementspath":{"eleLabel":"Ruta dels elements","eleTitlLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['cs']={"editor":"Textový editor","editorPanel":"Panel textového editoru","common":{"editorHelp":"Stiskněte ALT 0 pro nápovědu","browseServer":"Vybrat na serveru","url":"URL","protocol":"Protokol","upload":"Odeslat","uploadSubmit":"Odeslat na server","image":"Obrázek","flash":"Flash","form":"Formulář","checkbox":"Zaškrtávací políčko","radio":"Přepínač","textField":"Textové pole","textarea":"Textová oblast","hiddenField":"Skryté pole","button":"Tlačítko","select":"Seznam","imageButton":"Obrázkové tlačítko","notSet":"<nenastaveno>","id":"Id","name":"Jméno","langDir":"Směr jazyka","langDirLtr":"Zleva doprava (LTR)","langDirRtl":"Zprava doleva (RTL)","langCode":"Kód jazyka","longDescr":"Dlouhý popis URL","cssClass":"Třída stylu","advisoryTitle":"Pomocný titulek","cssStyle":"Styl","ok":"OK","cancel":"Zrušit","close":"Zavřít","preview":"Náhled","resize":"Uchopit pro změnu velikosti","generalTab":"Obecné","advancedTab":"Rozšířené","validateNumberFailed":"Zadaná hodnota není číselná.","confirmNewPage":"Jakékoliv neuložené změny obsahu budou ztraceny. Skutečně chcete otevřít novou stránku?","confirmCancel":"Některá z nastavení byla změněna. Skutečně chcete zavřít dialogové okno?","options":"Nastavení","target":"Cíl","targetNew":"Nové okno (_blank)","targetTop":"Okno nejvyšší úrovně (_top)","targetSelf":"Stejné okno (_self)","targetParent":"Rodičovské okno (_parent)","langDirLTR":"Zleva doprava (LTR)","langDirRTL":"Zprava doleva (RTL)","styles":"Styly","cssClasses":"Třídy stylů","width":"Šířka","height":"Výška","align":"Zarovnání","left":"Vlevo","right":"Vpravo","center":"Na střed","justify":"Zarovnat do bloku","alignLeft":"Zarovnat vlevo","alignRight":"Zarovnat vpravo","alignCenter":"Zarovnat na střed","alignTop":"Nahoru","alignMiddle":"Na střed","alignBottom":"Dolů","alignNone":"Žádné","invalidValue":"Neplatná hodnota.","invalidHeight":"Zadaná výška musí být číslo.","invalidWidth":"Šířka musí být číslo.","invalidLength":"Hodnota určená pro pole \"%1\" musí být kladné číslo bez nebo s platnou jednotkou míry (%2).","invalidCssLength":"Hodnota určená pro pole \"%1\" musí být kladné číslo bez nebo s platnou jednotkou míry CSS (px, %, in, cm, mm, em, ex, pt, nebo pc).","invalidHtmlLength":"Hodnota určená pro pole \"%1\" musí být kladné číslo bez nebo s platnou jednotkou míry HTML (px nebo %).","invalidInlineStyle":"Hodnota určená pro řádkový styl se musí skládat z jedné nebo více n-tic ve formátu \"název : hodnota\", oddělené středníky","cssLengthTooltip":"Zadejte číslo jako hodnotu v pixelech nebo číslo s platnou jednotkou CSS (px, %, v cm, mm, em, ex, pt, nebo pc).","unavailable":"%1<span class=\"cke_accessibility\">, nedostupné</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Mezerník","35":"Konec","36":"Domů","46":"Smazat","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Klávesová zkratka","optionDefault":"Výchozí"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"O aplikaci CKEditor 4","moreInfo":"Pro informace o lincenci navštivte naši webovou stránku:"},"basicstyles":{"bold":"Tučné","italic":"Kurzíva","strike":"Přeškrtnuté","subscript":"Dolní index","superscript":"Horní index","underline":"Podtržené"},"blockquote":{"toolbar":"Citace"},"notification":{"closed":"Oznámení zavřeno."},"toolbar":{"toolbarCollapse":"Skrýt panel nástrojů","toolbarExpand":"Zobrazit panel nástrojů","toolbarGroups":{"document":"Dokument","clipboard":"Schránka/Zpět","editing":"Úpravy","forms":"Formuláře","basicstyles":"Základní styly","paragraph":"Odstavec","links":"Odkazy","insert":"Vložit","styles":"Styly","colors":"Barvy","tools":"Nástroje"},"toolbars":"Panely nástrojů editoru"},"clipboard":{"copy":"Kopírovat","copyError":"Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro kopírování zvoleného textu do schránky. Prosím zkopírujte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+C).","cut":"Vyjmout","cutError":"Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+X).","paste":"Vložit","pasteNotification":"Stiskněte %1 pro vložení. Váš prohlížeč nepodporuje vkládání pomocí tlačítka na panelu nástrojů nebo volby kontextového menu.","pasteArea":"Oblast vkládání","pasteMsg":"Vložte svůj obsah do oblasti níže a stiskněte OK."},"contextmenu":{"options":"Nastavení kontextové nabídky"},"elementspLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['cy']={"editor":"Golygydd Testun Cyfoethog","editorPanel":"Panel Golygydd Testun Cyfoethog","common":{"editorHelp":"Gwasgwch ALT 0 am gymorth","browseServer":"Pori'r Gweinydd","url":"URL","protocol":"Protocol","upload":"Lanlwytho","uploadSubmit":"Anfon i'r Gweinydd","image":"Delwedd","flash":"Flash","form":"Ffurflen","checkbox":"Blwch ticio","radio":"Botwm Radio","textField":"Maes Testun","textarea":"Ardal Testun","hiddenField":"Maes Cudd","button":"Botwm","select":"Maes Dewis","imageButton":"Botwm Delwedd","notSet":"<heb osod>","id":"Id","name":"Name","langDir":"Cyfeiriad Iaith","langDirLtr":"Chwith i'r Dde (LTR)","langDirRtl":"Dde i'r Chwith (RTL)","langCode":"Cod Iaith","longDescr":"URL Disgrifiad Hir","cssClass":"Dosbarthiadau Dalen Arddull","advisoryTitle":"Teitl Cynghorol","cssStyle":"Arddull","ok":"Iawn","cancel":"Diddymu","close":"Cau","preview":"Rhagolwg","resize":"Ailfeintio","generalTab":"Cyffredinol","advancedTab":"Uwch","validateNumberFailed":"'Dyw'r gwerth hwn ddim yn rhif.","confirmNewPage":"Byddwch chi'n colli unrhyw newidiadau i'r cynnwys sydd heb eu cadw. Ydych am barhau i lwytho tudalen newydd?","confirmCancel":"Cafodd rhai o'r opsiynau eu newid. Ydych chi wir am gau'r deialog?","options":"Opsiynau","target":"Targed","targetNew":"Ffenest Newydd (_blank)","targetTop":"Ffenest ar y Brig (_top)","targetSelf":"Yr un Ffenest (_self)","targetParent":"Ffenest y Rhiant (_parent)","langDirLTR":"Chwith i'r Dde (LTR)","langDirRTL":"Dde i'r Chwith (RTL)","styles":"Arddull","cssClasses":"Dosbarthiadau Dalen Arddull","width":"Lled","height":"Uchder","align":"Alinio","left":"Chwith","right":"Dde","center":"Canol","justify":"Unioni","alignLeft":"Alinio i'r Chwith","alignRight":"Alinio i'r Dde","alignCenter":"Align Center","alignTop":"Brig","alignMiddle":"Canol","alignBottom":"Gwaelod","alignNone":"None","invalidValue":"Gwerth annilys.","invalidHeight":"Mae'n rhaid i'r uchder fod yn rhif.","invalidWidth":"Mae'n rhaid i'r lled fod yn rhif.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Mae'n rhaid i'r gwerth ar gyfer maes \"%1\" fod yn rhif positif gyda neu heb uned fesuriad CSS dilys (px, %, in, cm, mm, em, ex, pt, neu pc).","invalidHtmlLength":"Mae'n rhaid i'r gwerth ar gyfer maes \"%1\" fod yn rhif positif gyda neu heb uned fesuriad HTML dilys (px neu %).","invalidInlineStyle":"Mae'n rhaid i'r gwerth ar gyfer arddull mewn-llinell gynnwys un set neu fwy ar y fformat \"enw : gwerth\", wedi'u gwahanu gyda hanner colon.","cssLengthTooltip":"Rhowch rif am werth mewn picsel neu rhif gydag uned CSS dilys (px, %, in, cm, mm, em, pt neu pc).","unavailable":"%1<span class=\"cke_accessibility\">, ddim ar gael</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Hawlfraint © $1. Cedwir pob hawl.","dlgTitle":"About CKEditor 4","moreInfo":"Am wybodaeth ynghylch trwyddedau, ewch i'n gwefan:"},"basicstyles":{"bold":"Bras","italic":"Italig","strike":"Llinell Trwyddo","subscript":"Is-sgript","superscript":"Uwchsgript","underline":"Tanlinellu"},"blockquote":{"toolbar":"Dyfyniad bloc"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Cyfangu'r Bar Offer","toolbarExpand":"Ehangu'r Bar Offer","toolbarGroups":{"document":"Dogfen","clipboard":"Clipfwrdd/Dadwneud","editing":"Golygu","forms":"Ffurflenni","basicstyles":"Arddulliau Sylfaenol","paragraph":"Paragraff","links":"Dolenni","insert":"Mewnosod","styles":"Arddulliau","colors":"Lliwiau","tools":"Offer"},"toolbars":"Bariau offer y golygydd"},"clipboard":{"copy":"Copïo","copyError":"'Dyw gosodiadau diogelwch eich porwr ddim yn caniatàu'r golygydd i gynnal 'gweithredoedd copïo' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl/Cmd+C).","cut":"Torri","cutError":"Nid yw gosodiadau diogelwch eich porwr yn caniatàu'r golygydd i gynnal 'gweithredoedd torri' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl/Cmd+X).","paste":"Gludo","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Ardal Gludo","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Opsiynau Dewislen Cyd-destun"},"elementspath":{"eleLabel":"Llwybr elfennau","eleTitle":"Elfen %1"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['da']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Tryk ALT 0 for hjælp","browseServer":"Gennemse...","url":"URL","protocol":"Protokol","upload":"Upload","uploadSubmit":"Upload","image":"Indsæt billede","flash":"Indsæt Flash","form":"Indsæt formular","checkbox":"Indsæt afkrydsningsfelt","radio":"Indsæt alternativknap","textField":"Indsæt tekstfelt","textarea":"Indsæt tekstboks","hiddenField":"Indsæt skjult felt","button":"Indsæt knap","select":"Indsæt liste","imageButton":"Indsæt billedknap","notSet":"<intet valgt>","id":"Id","name":"Navn","langDir":"Tekstretning","langDirLtr":"Fra venstre mod højre (LTR)","langDirRtl":"Fra højre mod venstre (RTL)","langCode":"Sprogkode","longDescr":"Udvidet beskrivelse","cssClass":"Typografiark (CSS)","advisoryTitle":"Titel","cssStyle":"Typografi (CSS)","ok":"OK","cancel":"Annullér","close":"Luk","preview":"Forhåndsvisning","resize":"Træk for at skalere","generalTab":"Generelt","advancedTab":"Avanceret","validateNumberFailed":"Værdien er ikke et tal.","confirmNewPage":"Alt indhold, der ikke er blevet gemt, vil gå tabt. Er du sikker på, at du vil indlæse en ny side?","confirmCancel":"Nogle af indstillingerne er blevet ændret. Er du sikker på, at du vil lukke vinduet?","options":"Vis muligheder","target":"Mål","targetNew":"Nyt vindue (_blank)","targetTop":"Øverste vindue (_top)","targetSelf":"Samme vindue (_self)","targetParent":"Samme vindue (_parent)","langDirLTR":"Venstre til højre (LTR)","langDirRTL":"Højre til venstre (RTL)","styles":"Style","cssClasses":"Stylesheetklasser","width":"Bredde","height":"Højde","align":"Justering","left":"Venstre","right":"Højre","center":"Center","justify":"Lige margener","alignLeft":"Venstrestillet","alignRight":"Højrestillet","alignCenter":"Centreret","alignTop":"Øverst","alignMiddle":"Centreret","alignBottom":"Nederst","alignNone":"Ingen","invalidValue":"Ugyldig værdi.","invalidHeight":"Højde skal være et tal.","invalidWidth":"Bredde skal være et tal.","invalidLength":"Værdien angivet for feltet \"%1\" skal være et positivt heltal med eller uden en gyldig måleenhed (%2).","invalidCssLength":"Værdien specificeret for \"%1\" feltet skal være et positivt nummer med eller uden en CSS måleenhed (px, %, in, cm, mm, em, ex, pt, eller pc).","invalidHtmlLength":"Værdien specificeret for \"%1\" feltet skal være et positivt nummer med eller uden en CSS måleenhed (px eller %).","invalidInlineStyle":"Værdien specificeret for inline style skal indeholde en eller flere elementer med et format som \"name:value\", separeret af semikoloner","cssLengthTooltip":"Indsæt en numerisk værdi i pixel eller nummer med en gyldig CSS værdi (px, %, in, cm, mm, em, ex, pt, eller pc).","unavailable":"%1<span class=\"cke_accessibility\">, ikke tilgængelig</span>","keyboard":{"8":"Backspace","13":"Retur","16":"Shift","17":"Ctrl","18":"Alt","32":"Mellemrum","35":"End","36":"Home","46":"Slet","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Kommando"},"keyboardShortcut":"Tastatur genvej","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Alle rettigheder forbeholdes.","dlgTitle":"Om CKEditor 4","moreInfo":"For informationer omkring licens, se venligst vores hjemmeside (på engelsk):"},"basicstyles":{"bold":"Fed","italic":"Kursiv","strike":"Gennemstreget","subscript":"Sænket skrift","superscript":"Hævet skrift","underline":"Understreget"},"blockquote":{"toolbar":"Blokcitat"},"notification":{"closed":"Notefikation lukket."},"toolbar":{"toolbarCollapse":"Sammenklap værktøjslinje","toolbarExpand":"Udvid værktøjslinje","toolbarGroups":{"document":"Dokument","clipboard":"Udklipsholder/Fortryd","editing":"Redigering","forms":"Formularer","basicstyles":"Basis styles","paragraph":"Paragraf","links":"Links","insert":"Indsæt","styles":"Typografier","colors":"Farver","tools":"Værktøjer"},"toolbars":"Editors værktøjslinjer"},"clipboard":{"copy":"Kopiér","copyError":"Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.<br><br>Brug i stedet tastaturet til at kopiere teksten (Ctrl/Cmd+C).","cut":"Klip","cutError":"Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.<br><br>Brug i stedet tastaturet til at klippe teksten (Ctrl/Cmd+X).","paste":"Indsæt","pasteNotification":"Tryk %1 for at sætte ind. Din browser understøtter ikke indsættelse med værktøjslinje knappen eller kontekst menuen.","pasteArea":"Indsættelses område","pasteMsg":"Indsæt dit indhold i området nedenfor og tryk OK."},"contextmenu":{"options":"Muligheder for hjælpemenu"},"elementspath":{"eleLabel":"Sti på element","eleTitle":"%1 element"}Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['de-ch']={"editor":"WYSIWYG-Editor","editorPanel":"WYSIWYG-Editor-Leiste","common":{"editorHelp":"Drücken Sie ALT 0 für Hilfe","browseServer":"Server durchsuchen","url":"URL","protocol":"Protokoll","upload":"Hochladen","uploadSubmit":"Zum Server senden","image":"Bild","flash":"Flash","form":"Formular","checkbox":"Kontrollbox","radio":"Optionsfeld","textField":"Textfeld","textarea":"Textfeld","hiddenField":"Verstecktes Feld","button":"Schaltfläche","select":"Auswahlfeld","imageButton":"Bildschaltfläche","notSet":"<nicht festgelegt>","id":"Kennung","name":"Name","langDir":"Schreibrichtung","langDirLtr":"Links nach Rechts (LTR)","langDirRtl":"Rechts nach Links (RTL)","langCode":"Sprachcode","longDescr":"Langbeschreibungs-URL","cssClass":"Formatvorlagenklassen","advisoryTitle":"Titel Beschreibung","cssStyle":"Stil","ok":"OK","cancel":"Abbrechen","close":"Schliessen","preview":"Vorschau","resize":"Grösse ändern","generalTab":"Allgemein","advancedTab":"Erweitert","validateNumberFailed":"Dieser Wert ist keine Nummer.","confirmNewPage":"Alle nicht gespeicherten Änderungen gehen verlohren. Sind Sie sicher die neue Seite zu laden?","confirmCancel":"Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schliessen?","options":"Optionen","target":"Zielseite","targetNew":"Neues Fenster (_blank)","targetTop":"Oberstes Fenster (_top)","targetSelf":"Gleiches Fenster (_self)","targetParent":"Oberes Fenster (_parent)","langDirLTR":"Links nach Rechts (LNR)","langDirRTL":"Rechts nach Links (RNL)","styles":"Style","cssClasses":"Stylesheet Klasse","width":"Breite","height":"Höhe","align":"Ausrichtung","left":"Links","right":"Rechts","center":"Zentriert","justify":"Blocksatz","alignLeft":"Linksbündig","alignRight":"Rechtsbündig","alignCenter":"Align Center","alignTop":"Oben","alignMiddle":"Mitte","alignBottom":"Unten","alignNone":"Keine","invalidValue":"Ungültiger Wert.","invalidHeight":"Höhe muss eine Zahl sein.","invalidWidth":"Breite muss eine Zahl sein.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Wert spezifiziert für \"%1\" Feld muss ein positiver numerischer Wert sein mit oder ohne korrekte CSS Messeinheit (px, %, in, cm, mm, em, ex, pt oder pc).","invalidHtmlLength":"Wert spezifiziert für \"%1\" Feld muss ein positiver numerischer Wert sein mit oder ohne korrekte HTML Messeinheit (px oder %).","invalidInlineStyle":"Wert spezifiziert für inline Stilart muss enthalten ein oder mehr Tupels mit dem Format \"Name : Wert\" getrennt mit Semikolons.","cssLengthTooltip":"Gebe eine Zahl ein für ein Wert in pixels oder eine Zahl mit einer korrekten CSS Messeinheit (px, %, in, cm, mm, em, ex, pt oder pc).","unavailable":"%1<span class=\"cke_accessibility\">, nicht verfügbar</span>","keyboard":{"8":"Rücktaste","13":"Eingabe","16":"Umschalt","17":"Strg","18":"Alt","32":"Space","35":"Ende","36":"Pos1","46":"Entfernen","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Alle Rechte vorbehalten.","dlgTitle":"Über CKEditor 4","moreInfo":"Für Informationen über unsere Lizenzbestimmungen besuchen sie bitte unsere Webseite:"},"basicstyles":{"bold":"Fett","italic":"Kursiv","strike":"Durchgestrichen","subscript":"Tiefgestellt","superscript":"Hochgestellt","underline":"Unterstrichen"},"blockquote":{"toolbar":"Zitatblock"},"notification":{"closed":"Benachrichtigung geschlossen."},"toolbar":{"toolbarCollapse":"Werkzeugleiste einklappen","toolbarExpand":"Werkzeugleiste ausklappen","toolbarGroups":{"document":"Dokument","clipboard":"Zwischenablage/Rückgängig","editing":"Editieren","forms":"Formulare","basicstyles":"Grundstile","paragraph":"Absatz","links":"Links","insert":"Einfügen","styles":"Stile","colors":"Farben","tools":"Werkzeuge"},"toolbars":"Editor Werkzeugleisten"},"clipboard":{"copy":"Kopieren","copyError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).","cut":"Ausschneiden","cutError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).","paste":"Einfügen","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Einfügebereich","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Kontextmenüoptionen"},"elementspath":{"eleLabel":"Elementepfad","eleTitle":"%1 ElemeLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['de']={"editor":"WYSIWYG-Editor","editorPanel":"WYSIWYG-Editor-Leiste","common":{"editorHelp":"Drücken Sie ALT 0 für Hilfe","browseServer":"Server durchsuchen","url":"URL","protocol":"Protokoll","upload":"Hochladen","uploadSubmit":"Zum Server senden","image":"Bild","flash":"Flash","form":"Formular","checkbox":"Kontrollbox","radio":"Optionsfeld","textField":"Textfeld","textarea":"Textfeld","hiddenField":"Verstecktes Feld","button":"Schaltfläche","select":"Auswahlfeld","imageButton":"Bildschaltfläche","notSet":"<nicht festgelegt>","id":"Kennung","name":"Name","langDir":"Schreibrichtung","langDirLtr":"Links nach Rechts (LTR)","langDirRtl":"Rechts nach Links (RTL)","langCode":"Sprachcode","longDescr":"Langbeschreibungs-URL","cssClass":"Formatvorlagenklassen","advisoryTitle":"Titel Beschreibung","cssStyle":"Stil","ok":"OK","cancel":"Abbrechen","close":"Schließen","preview":"Vorschau","resize":"Größe ändern","generalTab":"Allgemein","advancedTab":"Erweitert","validateNumberFailed":"Dieser Wert ist keine Nummer.","confirmNewPage":"Alle nicht gespeicherten Änderungen gehen verloren. Sind Sie sicher die neue Seite zu laden?","confirmCancel":"Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schließen?","options":"Optionen","target":"Zielseite","targetNew":"Neues Fenster (_blank)","targetTop":"Oberstes Fenster (_top)","targetSelf":"Gleiches Fenster (_self)","targetParent":"Oberes Fenster (_parent)","langDirLTR":"Links nach Rechts (LNR)","langDirRTL":"Rechts nach Links (RNL)","styles":"Style","cssClasses":"Stylesheet Klasse","width":"Breite","height":"Höhe","align":"Ausrichtung","left":"Links","right":"Rechts","center":"Zentriert","justify":"Blocksatz","alignLeft":"Linksbündig","alignRight":"Rechtsbündig","alignCenter":"Zentriert","alignTop":"Oben","alignMiddle":"Mitte","alignBottom":"Unten","alignNone":"Keine","invalidValue":"Ungültiger Wert.","invalidHeight":"Höhe muss eine Zahl sein.","invalidWidth":"Breite muss eine Zahl sein.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Wert spezifiziert für \"%1\" Feld muss ein positiver numerischer Wert sein mit oder ohne korrekte CSS Messeinheit (px, %, in, cm, mm, em, ex, pt oder pc).","invalidHtmlLength":"Wert spezifiziert für \"%1\" Feld muss ein positiver numerischer Wert sein mit oder ohne korrekte HTML Messeinheit (px oder %).","invalidInlineStyle":"Wert spezifiziert für inline Stilart muss enthalten ein oder mehr Tupels mit dem Format \"Name : Wert\" getrennt mit Semikolons.","cssLengthTooltip":"Gebe eine Zahl ein für ein Wert in pixels oder eine Zahl mit einer korrekten CSS Messeinheit (px, %, in, cm, mm, em, ex, pt oder pc).","unavailable":"%1<span class=\"cke_accessibility\">, nicht verfügbar</span>","keyboard":{"8":"Rücktaste","13":"Eingabe","16":"Umschalt","17":"Strg","18":"Alt","32":"Leer","35":"Ende","36":"Pos1","46":"Entfernen","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Befehl"},"keyboardShortcut":"Tastaturkürzel","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Alle Rechte vorbehalten.","dlgTitle":"Über CKEditor 4","moreInfo":"Für Informationen über unsere Lizenzbestimmungen besuchen sie bitte unsere Webseite:"},"basicstyles":{"bold":"Fett","italic":"Kursiv","strike":"Durchgestrichen","subscript":"Tiefgestellt","superscript":"Hochgestellt","underline":"Unterstrichen"},"blockquote":{"toolbar":"Zitatblock"},"notification":{"closed":"Benachrichtigung geschlossen."},"toolbar":{"toolbarCollapse":"Werkzeugleiste einklappen","toolbarExpand":"Werkzeugleiste ausklappen","toolbarGroups":{"document":"Dokument","clipboard":"Zwischenablage/Rückgängig","editing":"Editieren","forms":"Formulare","basicstyles":"Grundstile","paragraph":"Absatz","links":"Links","insert":"Einfügen","styles":"Stile","colors":"Farben","tools":"Werkzeuge"},"toolbars":"Editor Werkzeugleisten"},"clipboard":{"copy":"Kopieren","copyError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).","cut":"Ausschneiden","cutError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).","paste":"Einfügen","pasteNotification":"Drücken Sie %1 zum Einfügen. Ihr Browser unterstützt nicht das Einfügen über dem Knopf in der Toolbar oder dem Kontextmenü.","pasteArea":"Einfügebereich","pasteMsg":"Fügen Sie den Inhalt in den unteren Bereich ein und drücken Sie OK."},"contextmenu":{"options":"Kontextmenüoptionen"},"elementspath":{"eleLabel":"ElemenLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['el']={"editor":"Επεξεργαστής Πλούσιου Κειμένου","editorPanel":"Πίνακας Επεξεργαστή Πλούσιου Κειμένου","common":{"editorHelp":"Πατήστε το ALT 0 για βοήθεια","browseServer":"Εξερεύνηση Διακομιστή","url":"URL","protocol":"Πρωτόκολλο","upload":"Αποστολή","uploadSubmit":"Αποστολή στον Διακομιστή","image":"Εικόνα","flash":"Flash","form":"Φόρμα","checkbox":"Κουτί Επιλογής","radio":"Κουμπί Επιλογής","textField":"Πεδίο Κειμένου","textarea":"Περιοχή Κειμένου","hiddenField":"Κρυφό Πεδίο","button":"Κουμπί","select":"Πεδίο Επιλογής","imageButton":"Κουμπί Εικόνας","notSet":"<δεν έχει ρυθμιστεί>","id":"Id","name":"Όνομα","langDir":"Κατεύθυνση Κειμένου","langDirLtr":"Αριστερά προς Δεξιά (LTR)","langDirRtl":"Δεξιά προς Αριστερά (RTL)","langCode":"Κωδικός Γλώσσας","longDescr":"Αναλυτική Περιγραφή URL","cssClass":"Κλάσεις Φύλλων Στυλ","advisoryTitle":"Ενδεικτικός Τίτλος","cssStyle":"Μορφή Κειμένου","ok":"OK","cancel":"Ακύρωση","close":"Κλείσιμο","preview":"Προεπισκόπηση","resize":"Αλλαγή Μεγέθους","generalTab":"Γενικά","advancedTab":"Για Προχωρημένους","validateNumberFailed":"Αυτή η τιμή δεν είναι αριθμός.","confirmNewPage":"Οι όποιες αλλαγές στο περιεχόμενο θα χαθούν. Είσαστε σίγουροι ότι θέλετε να φορτώσετε μια νέα σελίδα;","confirmCancel":"Μερικές επιλογές έχουν αλλάξει. Είσαστε σίγουροι ότι θέλετε να κλείσετε το παράθυρο διαλόγου;","options":"Επιλογές","target":"Προορισμός","targetNew":"Νέο Παράθυρο (_blank)","targetTop":"Αρχική Περιοχή (_top)","targetSelf":"Ίδιο Παράθυρο (_self)","targetParent":"Γονεϊκό Παράθυρο (_parent)","langDirLTR":"Αριστερά προς Δεξιά (LTR)","langDirRTL":"Δεξιά προς Αριστερά (RTL)","styles":"Μορφή","cssClasses":"Κλάσεις Φύλλων Στυλ","width":"Πλάτος","height":"Ύψος","align":"Στοίχιση","left":"Αριστερά","right":"Δεξιά","center":"Κέντρο","justify":"Πλήρης Στοίχιση","alignLeft":"Στοίχιση Αριστερά","alignRight":"Στοίχιση Δεξιά","alignCenter":"Align Center","alignTop":"Πάνω","alignMiddle":"Μέση","alignBottom":"Κάτω","alignNone":"Χωρίς","invalidValue":"Μη έγκυρη τιμή.","invalidHeight":"Το ύψος πρέπει να είναι ένας αριθμός.","invalidWidth":"Το πλάτος πρέπει να είναι ένας αριθμός.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Η τιμή που ορίζεται για το πεδίο \"%1\" πρέπει να είναι ένας θετικός αριθμός με ή χωρίς μια έγκυρη μονάδα μέτρησης CSS (px, %, in, cm, mm, em, ex, pt, ή pc).","invalidHtmlLength":"Η τιμή που ορίζεται για το πεδίο \"%1\" πρέπει να είναι ένας θετικός αριθμός με ή χωρίς μια έγκυρη μονάδα μέτρησης HTML (px ή %).","invalidInlineStyle":"Η τιμή για το εν σειρά στυλ πρέπει να περιέχει ένα ή περισσότερα ζεύγη με την μορφή \"όνομα: τιμή\" διαχωρισμένα με Ελληνικό ερωτηματικό.","cssLengthTooltip":"Εισάγεται μια τιμή σε pixel ή έναν αριθμό μαζί με μια έγκυρη μονάδα μέτρησης CSS (px, %, in, cm, mm, em, ex, pt, ή pc).","unavailable":"%1<span class=\"cke_accessibility\">, δεν είναι διαθέσιμο</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Κενό","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Εντολή"},"keyboardShortcut":"Συντόμευση πληκτρολογίου","optionDefault":"Default"},"about":{"copy":"Πνευματικά δικαιώματα © $1 Με επιφύλαξη παντός δικαιώματος.","dlgTitle":"Περί του CKEditor 4","moreInfo":"ΓLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['en-au']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Align","left":"Left","right":"Right","center":"Centre","justify":"Justify","alignLeft":"Align Left","alignRight":"Align Right","alignCenter":"Align Centre","alignTop":"Top","alignMiddle":"Middle","alignBottom":"Bottom","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strike Through","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"blockquote":{"toolbar":"Block Quote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError"Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['en-ca']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Align","left":"Left","right":"Right","center":"Centre","justify":"Justify","alignLeft":"Align Left","alignRight":"Align Right","alignCenter":"Align Center","alignTop":"Top","alignMiddle":"Middle","alignBottom":"Bottom","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strike Through","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"blockquote":{"toolbar":"Block Quote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError"Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['en-gb']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Drag to resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialogue window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Align","left":"Left","right":"Right","center":"Center","justify":"Justify","alignLeft":"Align Left","alignRight":"Align Right","alignCenter":"Align Center","alignTop":"Top","alignMiddle":"Middle","alignBottom":"Bottom","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strike Through","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"blockquote":{"toolbar":"Block Quote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","nLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['en']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Alignment","left":"Left","right":"Right","center":"Center","justify":"Justify","alignLeft":"Align Left","alignRight":"Align Right","alignCenter":"Align Center","alignTop":"Top","alignMiddle":"Middle","alignBottom":"Bottom","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strikethrough","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"blockquote":{"toolbar":"Block Quote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError"Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['eo']={"editor":"RiĉTeksta Redaktilo","editorPanel":"Panelo de la RiĉTeksta Redaktilo","common":{"editorHelp":"Premu ALT 0 por helpilo","browseServer":"Foliumi en la Servilo","url":"URL","protocol":"Protokolo","upload":"Alŝuti","uploadSubmit":"Sendu al Servilo","image":"Bildo","flash":"Flaŝo","form":"Formularo","checkbox":"Markobutono","radio":"Radiobutono","textField":"Teksta kampo","textarea":"Teksta Areo","hiddenField":"Kaŝita Kampo","button":"Butono","select":"Elekta Kampo","imageButton":"Bildbutono","notSet":"<Defaŭlta>","id":"Id","name":"Nomo","langDir":"Skribdirekto","langDirLtr":"De maldekstro dekstren (LTR)","langDirRtl":"De dekstro maldekstren (RTL)","langCode":"Lingva Kodo","longDescr":"URL de Longa Priskribo","cssClass":"Klasoj de Stilfolioj","advisoryTitle":"Priskriba Titolo","cssStyle":"Stilo","ok":"Akcepti","cancel":"Rezigni","close":"Fermi","preview":"Vidigi Aspekton","resize":"Movigi por ŝanĝi la grandon","generalTab":"Ĝenerala","advancedTab":"Speciala","validateNumberFailed":"Tiu valoro ne estas nombro.","confirmNewPage":"La neregistritaj ŝanĝoj estas perdotaj. Ĉu vi certas, ke vi volas ŝargi novan paĝon?","confirmCancel":"Iuj opcioj esta ŝanĝitaj. Ĉu vi certas, ke vi volas fermi la dialogon?","options":"Opcioj","target":"Celo","targetNew":"Nova Fenestro (_blank)","targetTop":"Supra Fenestro (_top)","targetSelf":"Sama Fenestro (_self)","targetParent":"Patra Fenestro (_parent)","langDirLTR":"De maldekstro dekstren (LTR)","langDirRTL":"De dekstro maldekstren (RTL)","styles":"Stilo","cssClasses":"Stilfoliaj Klasoj","width":"Larĝo","height":"Alto","align":"Ĝisrandigo","left":"Maldekstre","right":"Dekstre","center":"Centre","justify":"Ĝisrandigi Ambaŭflanke","alignLeft":"Ĝisrandigi maldekstren","alignRight":"Ĝisrandigi dekstren","alignCenter":"Align Center","alignTop":"Supre","alignMiddle":"Centre","alignBottom":"Malsupre","alignNone":"Neniu","invalidValue":"Nevalida Valoro","invalidHeight":"Alto devas esti nombro.","invalidWidth":"Larĝo devas esti nombro.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"La valoro indikita por la \"%1\" kampo devas esti pozitiva nombro kun aŭ sen valida CSSmezurunuo (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"La valoro indikita por la \"%1\" kampo devas esti pozitiva nombro kun aŭ sen valida HTMLmezurunuo (px or %).","invalidInlineStyle":"La valoro indikita por la enlinia stilo devas konsisti el unu aŭ pluraj elementoj kun la formato de \"nomo : valoro\", apartigitaj per punktokomoj.","cssLengthTooltip":"Entajpu nombron por rastrumera valoro aŭ nombron kun valida CSSunuo (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, nehavebla</span>","keyboard":{"8":"Retropaŝo","13":"Enigi","16":"Registrumo","17":"Stirklavo","18":"Alt-klavo","32":"Spaco","35":"Fino","36":"Hejmo","46":"Forigi","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Komando"},"keyboardShortcut":"Fulmoklavo","optionDefault":"Defaŭlta"},"about":{"copy":"Copyright © $1. Ĉiuj rajtoj rezervitaj.","dlgTitle":"Pri CKEditor 4","moreInfo":"Por informoj pri licenco, bonvolu viziti nian retpaĝaron:"},"basicstyles":{"bold":"Grasa","italic":"Kursiva","strike":"Trastreko","subscript":"Suba indico","superscript":"Supra indico","underline":"Substreko"},"blockquote":{"toolbar":"Citaĵo"},"notification":{"closed":"Sciigo fermita"},"toolbar":{"toolbarCollapse":"Faldi la ilbreton","toolbarExpand":"Malfaldi la ilbreton","toolbarGroups":{"document":"Dokumento","clipboard":"Poŝo/Malfari","editing":"Redaktado","forms":"Formularoj","basicstyles":"Bazaj stiloj","paragraph":"Paragrafo","links":"Ligiloj","insert":"Enmeti","styles":"Stiloj","colors":"Koloroj","tools":"Iloj"},"toolbars":"Ilobretoj de la redaktilo"},"clipboard":{"copy":"Kopii","copyError":"La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras kopiajn operaciojn. Bonvolu uzi la klavaron por tio (Ctrl/Cmd-C).","cut":"Eltondi","cutError":"La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras eltondajn operaciojn. Bonvolu uzi la klavaron por tio (Ctrl/Cmd-X).","paste":"Interglui","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Intergluoareo","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Opcioj de Kunteksta Menuo"},"elementspath":{"eleLabel":"Vojo al Elementoj","eleTitle":"%1 elementoj"},"filetools":{"loadError":"Eraro okazis dum la dosiera legado.","networkError":"Reta eraro okazis dum la dosiera alŝuto.","httpError404":"HTTP eraro okazis dum la dosierLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['es-mx']={"editor":"Editor de texto enriquecido","editorPanel":"Panel del editor de texto","common":{"editorHelp":"Presiona ALT + 0 para ayuda","browseServer":"Examinar servidor","url":"URL","protocol":"Protocolo","upload":"Subir","uploadSubmit":"Enviar al servidor","image":"Imagen","flash":"Flash","form":"Formulario","checkbox":"Casilla de verificación","radio":"Botón de opción","textField":"Campo de texto","textarea":"Área de texto","hiddenField":"Campo oculto","button":"Botón","select":"Campo de selección","imageButton":"Botón de imagen","notSet":"<not set>","id":"Id","name":"Nombre","langDir":"Dirección de idiomas","langDirLtr":"Izquierda a derecha (LTR)","langDirRtl":"Derecha a izquierda (RTL)","langCode":"Código de lenguaje","longDescr":"URL descripción larga","cssClass":"Clases de hoja de estilo","advisoryTitle":"Título del anuncio","cssStyle":"Estilo","ok":"OK","cancel":"Cancelar","close":"Cerrar","preview":"Vista previa","resize":"Redimensionar","generalTab":"General","advancedTab":"Avanzada","validateNumberFailed":"Este valor no es un número.","confirmNewPage":"Se perderán todos los cambios no guardados en este contenido. ¿Seguro que quieres cargar nueva página?","confirmCancel":"Ha cambiado algunas opciones. ¿Está seguro de que desea cerrar la ventana de diálogo?","options":"Opciones","target":"Objetivo","targetNew":"Nueva ventana (_blank)","targetTop":"Ventana superior (_top)","targetSelf":"Misma ventana (_self)","targetParent":"Ventana principal (_parent)","langDirLTR":"Izquierda a Derecha (LTR)","langDirRTL":"Derecha a Izquierda (RTL)","styles":"Estilo","cssClasses":"Clases de hojas de estilo","width":"Ancho","height":"Alto","align":"Alineación","left":"Izquierda","right":"Derecha","center":"Centrado","justify":"Justificado","alignLeft":"Alinear a la izquierda","alignRight":"Alinear a la derecha","alignCenter":"Align Center","alignTop":"Arriba","alignMiddle":"En medio","alignBottom":"Abajo","alignNone":"Ninguno","invalidValue":"Valor inválido","invalidHeight":"La altura debe ser un número.","invalidWidth":"La anchura debe ser un número.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"El valor especificado para el campo \"% 1\" debe ser un número positivo con o sin una unidad de medida CSS válida (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"El valor especificado para el campo \"% 1\" debe ser un número positivo con o sin una unidad de medición HTML válida (px or %).","invalidInlineStyle":"El valor especificado para el estilo en línea debe constar de una o más tuplas con el formato de \"nombre: valor\", separados por punto y coma","cssLengthTooltip":"Introduzca un número para un valor en píxeles o un número con una unidad CSS válida (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, no disponible</span>","keyboard":{"8":"Retroceso","13":"Intro","16":"Shift","17":"Ctrl","18":"Alt","32":"Espacio","35":"Fin","36":"Inicio","46":"Borrar","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Comando"},"keyboardShortcut":"Atajo de teclado","optionDefault":"Default"},"about":{"copy":"Derechos reservados © $1. Todos los derechos reservados","dlgTitle":"Acerca de CKEditor 4","moreInfo":"Para información sobre la licencia por favor visita nuestro sitio web:"},"basicstyles":{"bold":"Negrita","italic":"Cursiva","strike":"Tachado","subscript":"subíndice","superscript":"Sobrescrito","underline":"Subrayada"},"blockquote":{"toolbar":"Entrecomillado"},"notification":{"closed":"Notificación cerrada."},"toolbar":{"toolbarCollapse":"Colapsar barra de herramientas","toolbarExpand":"Expandir barra de herramientas","toolbarGroups":{"document":"Documento","clipboard":"Portapapeles/deshacer","editing":"Editando","forms":"Formularios","basicstyles":"Estilo básico","paragraph":"Párrafo","links":"Enlaces","insert":"Insertar","styles":"Estilos","colors":"Colores","tools":"Herramientas"},"toolbars":"Editor de barra de herramientas"},"clipboard":{"copy":"Copiar","copyError":"La configuración de seguridad de su navegador no permite al editor ejecutar automáticamente operaciones de copiado. Por favor, utilice el teclado para (Ctrl/Cmd+C).","cut":"Cortar","cutError":"La configuración de seguridad de su navegador no permite al editor ejecutar automáticamente operaciones de corte. Por favor, utilice el teclado para (Ctrl/Cmd+X).","paste":"Pegar","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"optioLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['es']={"editor":"Editor de texto enriquecido","editorPanel":"Panel del Editor de Texto Enriquecido","common":{"editorHelp":"Pulse ALT 0 para ayuda","browseServer":"Ver Servidor","url":"URL","protocol":"Protocolo","upload":"Cargar","uploadSubmit":"Enviar al Servidor","image":"Imagen","flash":"Flash","form":"Formulario","checkbox":"Casilla de Verificación","radio":"Botones de Radio","textField":"Campo de Texto","textarea":"Area de Texto","hiddenField":"Campo Oculto","button":"Botón","select":"Campo de Selección","imageButton":"Botón Imagen","notSet":"<No definido>","id":"Id","name":"Nombre","langDir":"Orientación","langDirLtr":"Izquierda a Derecha (LTR)","langDirRtl":"Derecha a Izquierda (RTL)","langCode":"Cód. de idioma","longDescr":"Descripción larga URL","cssClass":"Clases de hojas de estilo","advisoryTitle":"Título","cssStyle":"Estilo","ok":"Aceptar","cancel":"Cancelar","close":"Cerrar","preview":"Previsualización","resize":"Arrastre para redimensionar","generalTab":"General","advancedTab":"Avanzado","validateNumberFailed":"El valor no es un número.","confirmNewPage":"Cualquier cambio que no se haya guardado se perderá.\r\n¿Está seguro de querer crear una nueva página?","confirmCancel":"Algunas de las opciones se han cambiado.\r\n¿Está seguro de querer cerrar el diálogo?","options":"Opciones","target":"Destino","targetNew":"Nueva ventana (_blank)","targetTop":"Ventana principal (_top)","targetSelf":"Misma ventana (_self)","targetParent":"Ventana padre (_parent)","langDirLTR":"Izquierda a derecha (LTR)","langDirRTL":"Derecha a izquierda (RTL)","styles":"Estilos","cssClasses":"Clase de la hoja de estilos","width":"Anchura","height":"Altura","align":"Alineación","left":"Izquierda","right":"Derecha","center":"Centrado","justify":"Justificado","alignLeft":"Alinear a Izquierda","alignRight":"Alinear a Derecha","alignCenter":"Align Center","alignTop":"Tope","alignMiddle":"Centro","alignBottom":"Pie","alignNone":"Ninguno","invalidValue":"Valor no válido","invalidHeight":"Altura debe ser un número.","invalidWidth":"Anchura debe ser un número.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"El valor especificado para el campo \"%1\" debe ser un número positivo, incluyendo optionalmente una unidad de medida CSS válida (px, %, in, cm, mm, em, ex, pt, o pc).","invalidHtmlLength":"El valor especificado para el campo \"%1\" debe ser un número positivo, incluyendo optionalmente una unidad de medida HTML válida (px o %).","invalidInlineStyle":"El valor especificado para el estilo debe consistir en uno o más pares con el formato \"nombre: valor\", separados por punto y coma.","cssLengthTooltip":"Introduca un número para el valor en pixels o un número con una unidad de medida CSS válida (px, %, in, cm, mm, em, ex, pt, o pc).","unavailable":"%1<span class=\"cke_accessibility\">, no disponible</span>","keyboard":{"8":"Retroceso","13":"Ingresar","16":"Mayús.","17":"Ctrl","18":"Alt","32":"Space","35":"Fin","36":"Inicio","46":"Suprimir","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Todos los derechos reservados.","dlgTitle":"Acerca de CKEditor 4","moreInfo":"Para información de licencia, por favor visite nuestro sitio web:"},"basicstyles":{"bold":"Negrita","italic":"Cursiva","strike":"Tachado","subscript":"Subíndice","superscript":"Superíndice","underline":"Subrayado"},"blockquote":{"toolbar":"Cita"},"notification":{"closed":"Notificación cerrada."},"toolbar":{"toolbarCollapse":"Contraer barra de herramientas","toolbarExpand":"Expandir barra de herramientas","toolbarGroups":{"document":"Documento","clipboard":"Portapapeles/Deshacer","editing":"Edición","forms":"Formularios","basicstyles":"Estilos básicos","paragraph":"Párrafo","links":"Enlaces","insert":"Insertar","styles":"Estilos","colors":"Colores","tools":"Herramientas"},"toolbars":"Barras de herramientas del editor"},"clipboard":{"copy":"Copiar","copyError":"La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de copiado.\r\nPor favor use el teclado (Ctrl/Cmd+C).","cut":"Cortar","cutError":"La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado.\r\nPor favor use el teclado (Ctrl/Cmd+X).","paste":"Pegar","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Zona de pegado","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Opciones del menú contLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['et']={"editor":"Rikkalik tekstiredaktor","editorPanel":"Rikkaliku tekstiredaktori paneel","common":{"editorHelp":"Abi saamiseks vajuta ALT 0","browseServer":"Serveri sirvimine","url":"URL","protocol":"Protokoll","upload":"Laadi üles","uploadSubmit":"Saada serverisse","image":"Pilt","flash":"Flash","form":"Vorm","checkbox":"Märkeruut","radio":"Raadionupp","textField":"Tekstilahter","textarea":"Tekstiala","hiddenField":"Varjatud lahter","button":"Nupp","select":"Valiklahter","imageButton":"Piltnupp","notSet":"<määramata>","id":"ID","name":"Nimi","langDir":"Keele suund","langDirLtr":"Vasakult paremale (LTR)","langDirRtl":"Paremalt vasakule (RTL)","langCode":"Keele kood","longDescr":"Pikk kirjeldus URL","cssClass":"Stiilistiku klassid","advisoryTitle":"Soovituslik pealkiri","cssStyle":"Laad","ok":"Olgu","cancel":"Loobu","close":"Sulge","preview":"Eelvaade","resize":"Suuruse muutmiseks lohista","generalTab":"Üldine","advancedTab":"Täpsemalt","validateNumberFailed":"See väärtus pole number.","confirmNewPage":"Kõik salvestamata muudatused lähevad kaotsi. Kas oled kindel, et tahad laadida uue lehe?","confirmCancel":"Mõned valikud on muudetud. Kas oled kindel, et tahad dialoogi sulgeda?","options":"Valikud","target":"Sihtkoht","targetNew":"Uus aken (_blank)","targetTop":"Kõige ülemine aken (_top)","targetSelf":"Sama aken (_self)","targetParent":"Vanemaken (_parent)","langDirLTR":"Vasakult paremale (LTR)","langDirRTL":"Paremalt vasakule (RTL)","styles":"Stiili","cssClasses":"Stiililehe klassid","width":"Laius","height":"Kõrgus","align":"Joondus","left":"Vasak","right":"Paremale","center":"Kesk","justify":"Rööpjoondus","alignLeft":"Vasakjoondus","alignRight":"Paremjoondus","alignCenter":"Align Center","alignTop":"Üles","alignMiddle":"Keskele","alignBottom":"Alla","alignNone":"Pole","invalidValue":"Vigane väärtus.","invalidHeight":"Kõrgus peab olema number.","invalidWidth":"Laius peab olema number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"\"%1\" välja jaoks määratud väärtus peab olema positiivne täisarv CSS ühikuga (px, %, in, cm, mm, em, ex, pt või pc) või ilma.","invalidHtmlLength":"\"%1\" välja jaoks määratud väärtus peab olema positiivne täisarv HTML ühikuga (px või %) või ilma.","invalidInlineStyle":"Reasisese stiili määrangud peavad koosnema paarisväärtustest (tuples), mis on semikoolonitega eraldatult järgnevas vormingus: \"nimi : väärtus\".","cssLengthTooltip":"Sisesta väärtus pikslites või number koos sobiva CSS-i ühikuga (px, %, in, cm, mm, em, ex, pt või pc).","unavailable":"%1<span class=\"cke_accessibility\">, pole saadaval</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Tühik","35":"End","36":"Home","46":"Kustuta","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Vaikeväärtus"},"about":{"copy":"Copyright © $1. Kõik õigused kaitstud.","dlgTitle":"About CKEditor 4","moreInfo":"Litsentsi andmed leiab meie veebilehelt:"},"basicstyles":{"bold":"Paks","italic":"Kursiiv","strike":"Läbijoonitud","subscript":"Allindeks","superscript":"Ülaindeks","underline":"Allajoonitud"},"blockquote":{"toolbar":"Blokktsitaat"},"notification":{"closed":"Teavitused on suletud."},"toolbar":{"toolbarCollapse":"Tööriistariba peitmine","toolbarExpand":"Tööriistariba näitamine","toolbarGroups":{"document":"Dokument","clipboard":"Lõikelaud/tagasivõtmine","editing":"Muutmine","forms":"Vormid","basicstyles":"Põhistiilid","paragraph":"Lõik","links":"Lingid","insert":"Sisesta","styles":"Stiilid","colors":"Värvid","tools":"Tööriistad"},"toolbars":"Redaktori tööriistaribad"},"clipboard":{"copy":"Kopeeri","copyError":"Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt kopeerida. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+C).","cut":"Lõika","cutError":"Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).","paste":"Aseta","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Asetamise ala","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Kontekstimenüü valikud"},"elementspath":{"eleLabel":"Elementide asukoht","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error oLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['eu']={"editor":"Testu aberastuaren editorea","editorPanel":"Testu aberastuaren editorearen panela","common":{"editorHelp":"Sakatu ALT 0 laguntza jasotzeko","browseServer":"Arakatu zerbitzaria","url":"URLa","protocol":"Protokoloa","upload":"Kargatu","uploadSubmit":"Bidali zerbitzarira","image":"Irudia","flash":"Flash","form":"Formularioa","checkbox":"Kontrol-laukia","radio":"Aukera-botoia","textField":"Testu-eremua","textarea":"Testu-area","hiddenField":"Ezkutuko eremua","button":"Botoia","select":"Hautespen-eremua","imageButton":"Irudi-botoia","notSet":"<ezarri gabe>","id":"Id","name":"Izena","langDir":"Hizkuntzaren norabidea","langDirLtr":"Ezkerretik eskuinera (LTR)","langDirRtl":"Eskuinetik ezkerrera (RTL)","langCode":"Hizkuntzaren kodea","longDescr":"URLaren deskribapen luzea","cssClass":"Estilo-orriko klaseak","advisoryTitle":"Aholkatutako izenburua","cssStyle":"Estiloa","ok":"Ados","cancel":"Utzi","close":"Itxi","preview":"Aurrebista","resize":"Aldatu tamainaz","generalTab":"Orokorra","advancedTab":"Aurreratua","validateNumberFailed":"Balio hau ez da zenbaki bat.","confirmNewPage":"Eduki honetan gorde gabe dauden aldaketak galduko dira. Ziur zaude orri berri bat kargatu nahi duzula?","confirmCancel":"Aukera batzuk aldatu dituzu. Ziur zaude elkarrizketa-koadroa itxi nahi duzula?","options":"Aukerak","target":"Helburua","targetNew":"Leiho berria (_blank)","targetTop":"Goieneko leihoan (_top)","targetSelf":"Leiho berean (_self)","targetParent":"Leiho gurasoan (_parent)","langDirLTR":"Ezkerretik eskuinera (LTR)","langDirRTL":"Eskuinetik ezkerrera (RTL)","styles":"Estiloa","cssClasses":"Estilo-orriko klaseak","width":"Zabalera","height":"Altuera","align":"Lerrokatzea","left":"Ezkerrean","right":"Eskuinean","center":"Erdian","justify":"Justifikatu","alignLeft":"Lerrokatu ezkerrean","alignRight":"Lerrokatu eskuinean","alignCenter":"Align Center","alignTop":"Goian","alignMiddle":"Erdian","alignBottom":"Behean","alignNone":"Bat ere ez","invalidValue":"Balio desegokia.","invalidHeight":"Altuera zenbaki bat izan behar da.","invalidWidth":"Zabalera zenbaki bat izan behar da.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"\"%1\" eremurako zehaztutako balioak zenbaki positibo bat izan behar du, CSS neurri unitate batekin edo gabe (px, %, in, cm, mm, em, ex, pt edo pc).","invalidHtmlLength":"\"%1\" eremurako zehaztutako balioak zenbaki positibo bat izan behar du, HTML neurri unitate batekin edo gabe (px edo %).","invalidInlineStyle":"Lineako estiloan zehaztutako balioak \"izen : balio\" formatuko tupla bat edo gehiago izan behar dira, komaz bereiztuak.","cssLengthTooltip":"Sartu zenbaki bat edo zenbaki bat baliozko CSS unitate batekin (px, %, in, cm, mm, em, ex, pt, edo pc).","unavailable":"%1<span class=\"cke_accessibility\">, erabilezina</span>","keyboard":{"8":"Atzera tekla","13":"Sartu","16":"Maius","17":"Ktrl","18":"Alt","32":"Zuriunea","35":"Buka","36":"Etxea","46":"Ezabatu","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Komandoa"},"keyboardShortcut":"Laster-tekla","optionDefault":"Lehenetsia"},"about":{"copy":"Copyright © $1. Eskubide guztiak erreserbaturik.","dlgTitle":"CKEditor 4ri buruz","moreInfo":"Lizentziari buruzko informazioa gure webgunean:"},"basicstyles":{"bold":"Lodia","italic":"Etzana","strike":"Marratua","subscript":"Azpi-indizea","superscript":"Goi-indizea","underline":"Azpimarratu"},"blockquote":{"toolbar":"Aipamen blokea"},"notification":{"closed":"Jakinarazpena itxita."},"toolbar":{"toolbarCollapse":"Tolestu tresna-barra","toolbarExpand":"Zabaldu tresna-barra","toolbarGroups":{"document":"Dokumentua","clipboard":"Arbela/Desegin","editing":"Editatu","forms":"Formularioak","basicstyles":"Oinarrizko estiloak","paragraph":"Paragrafoa","links":"Estekak","insert":"Txertatu","styles":"Estiloak","colors":"Koloreak","tools":"Tresnak"},"toolbars":"Editorearen tresna-barrak"},"clipboard":{"copy":"Kopiatu","copyError":"Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki kopiatzea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+C).","cut":"Ebaki","cutError":"Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki moztea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+X).","paste":"Itsatsi","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Itsasteko area","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Testuinguru-menuaren aukerak"},"elementspath":{"eleLabel":"Elementuen bidea","eleTitle":"%1 elementua"},"filetools":{"loadError":"Errorea gertatu da fitxategia irakuLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['fa']={"editor":"ویرایشگر متن غنی","editorPanel":"پنل ویرایشگر متن غنی","common":{"editorHelp":"کلید Alt+0 را برای راهنمایی بفشارید","browseServer":"فهرستنمایی سرور","url":"URL","protocol":"قرارداد","upload":"بالاگذاری","uploadSubmit":"به سرور بفرست","image":"تصویر","flash":"فلش","form":"فرم","checkbox":"چکباکس","radio":"دکمهی رادیویی","textField":"فیلد متنی","textarea":"ناحیهٴ متنی","hiddenField":"فیلد پنهان","button":"دکمه","select":"فیلد انتخاب چند گزینهای","imageButton":"دکمهی تصویری","notSet":"<تعییننشده>","id":"شناسه","name":"نام","langDir":"جهت زبان","langDirLtr":"چپ به راست","langDirRtl":"راست به چپ","langCode":"کد زبان","longDescr":"URL توصیف طولانی","cssClass":"کلاسهای شیوهنامه (Stylesheet)","advisoryTitle":"عنوان کمکی","cssStyle":"سبک","ok":"پذیرش","cancel":"انصراف","close":"بستن","preview":"پیشنمایش","resize":"تغییر اندازه","generalTab":"عمومی","advancedTab":"پیشرفته","validateNumberFailed":"این مقدار یک عدد نیست.","confirmNewPage":"هر تغییر ایجاد شدهی ذخیره نشده از بین خواهد رفت. آیا اطمینان دارید که قصد بارگیری صفحه جدیدی را دارید؟","confirmCancel":"برخی از گزینهها تغییر کردهاند. آیا واقعا قصد بستن این پنجره را دارید؟","options":"گزینهها","target":"مقصد","targetNew":"پنجره جدید","targetTop":"بالاترین پنجره","targetSelf":"همان پنجره","targetParent":"پنجره والد","langDirLTR":"چپ به راست","langDirRTL":"راست به چپ","styles":"سبک","cssClasses":"کلاسهای سبکنامه","width":"عرض","height":"طول","align":"چینش","left":"چپ","right":"راست","center":"وسط","justify":"بلوک چین","alignLeft":"چپ چین","alignRight":"راست چین","alignCenter":"مرکز قرار بده","alignTop":"بالا","alignMiddle":"میانه","alignBottom":"پائین","alignNone":"هیچ","invalidValue":"مقدار نامعتبر.","invalidHeight":"ارتفاع باید یک عدد باشد.","invalidWidth":"عرض باید یک عدد باشد.","invalidLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری معتبر (\"%2\") باشد.","invalidCssLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری CSS معتبر باشد (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری HTML معتبر باشد (px or %).","invalidInlineStyle":"عدد تعیین شده برای سبک درونخطی -Inline Style- باید دارای یک یا چند چندتایی با شکلی شبیه \"name : value\" که باید با یک \";\" از هم جدا شوند.","cssLengthTooltip":"یک عدد برای یک مقدار بر حسب پیکسل و یا یک عدد با یک واحد CSS معتبر وارد کنید (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">، غیر قابل دسترس</span>","keyboard":{"8":"عقبگرد","13":"ورود","16":"تعویض","17":"کنترل","18":"دگرساز","32":"فاصله","35":"پایان","36":"خانه","46":"حذف","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"فرمان"},"keyboardShortcut":"میانبر صفحه کلید","optionDefault":"پیش فرض"},"about":{"copy":"حق نشر © $1. کلیه حقوق محفوظ است.","dlgTitle":"درباره CKEditor","moreInfo":"برای کسب اطلاعات مجوز لطفا به وب سایت ما مراجعه کنید:"},"basicstyles":{"bold":"درشت","italic":"خمیده","strike":"خطخورده","subscript":"زیرنویس","superscript":"بالانویس","underline":"زیرخطدار"},"blockquote":{"toolbar":"بلوک نقل قول"},"notification":{"closed":"آگاهسازی بسته شد"},"toolbar":{"toolbarCollapse":"بستن نوار ابزار","toolbarExpand":"بازکردن نوار ابزار","toolbarGroups":{"document":"سند","clipboard":"حافظه موقت/برگشت","editing":"در حال ویرایش","forms":"فرمها","basicstyles":"سبکهای پایه","paraLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['fi']={"editor":"Rikastekstieditori","editorPanel":"Rikastekstieditoripaneeli","common":{"editorHelp":"Paina ALT 0 nähdäksesi ohjeen","browseServer":"Selaa palvelinta","url":"Osoite","protocol":"Protokolla","upload":"Lisää tiedosto","uploadSubmit":"Lähetä palvelimelle","image":"Kuva","flash":"Flash-animaatio","form":"Lomake","checkbox":"Valintaruutu","radio":"Radiopainike","textField":"Tekstikenttä","textarea":"Tekstilaatikko","hiddenField":"Piilokenttä","button":"Painike","select":"Valintakenttä","imageButton":"Kuvapainike","notSet":"<ei asetettu>","id":"Tunniste","name":"Nimi","langDir":"Kielen suunta","langDirLtr":"Vasemmalta oikealle (LTR)","langDirRtl":"Oikealta vasemmalle (RTL)","langCode":"Kielikoodi","longDescr":"Pitkän kuvauksen URL","cssClass":"Tyyliluokat","advisoryTitle":"Avustava otsikko","cssStyle":"Tyyli","ok":"OK","cancel":"Peruuta","close":"Sulje","preview":"Esikatselu","resize":"Raahaa muuttaaksesi kokoa","generalTab":"Yleinen","advancedTab":"Lisäominaisuudet","validateNumberFailed":"Arvon pitää olla numero.","confirmNewPage":"Kaikki tallentamattomat muutokset tähän sisältöön menetetään. Oletko varma, että haluat ladata uuden sivun?","confirmCancel":"Jotkut asetuksista on muuttuneet. Oletko varma, että haluat sulkea valintaikkunan?","options":"Asetukset","target":"Kohde","targetNew":"Uusi ikkuna (_blank)","targetTop":"Päällimmäinen ikkuna (_top)","targetSelf":"Sama ikkuna (_self)","targetParent":"Ylemmän tason ikkuna (_parent)","langDirLTR":"Vasemmalta oikealle (LTR)","langDirRTL":"Oikealta vasemmalle (RTL)","styles":"Tyyli","cssClasses":"Tyylitiedoston luokat","width":"Leveys","height":"Korkeus","align":"Kohdistus","left":"Vasemmalle","right":"Oikealle","center":"Keskelle","justify":"Tasaa molemmat reunat","alignLeft":"Tasaa vasemmat reunat","alignRight":"Tasaa oikeat reunat","alignCenter":"Align Center","alignTop":"Ylös","alignMiddle":"Keskelle","alignBottom":"Alas","alignNone":"Ei asetettu","invalidValue":"Virheellinen arvo.","invalidHeight":"Korkeuden täytyy olla numero.","invalidWidth":"Leveyden täytyy olla numero.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Kentän \"%1\" arvon täytyy olla positiivinen luku CSS mittayksikön (px, %, in, cm, mm, em, ex, pt tai pc) kanssa tai ilman.","invalidHtmlLength":"Kentän \"%1\" arvon täytyy olla positiivinen luku HTML mittayksikön (px tai %) kanssa tai ilman.","invalidInlineStyle":"Tyylille annetun arvon täytyy koostua yhdestä tai useammasta \"nimi : arvo\" parista, jotka ovat eroteltuna toisistaan puolipisteillä.","cssLengthTooltip":"Anna numeroarvo pikseleinä tai numeroarvo CSS mittayksikön kanssa (px, %, in, cm, mm, em, ex, pt, tai pc).","unavailable":"%1<span class=\"cke_accessibility\">, ei saatavissa</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Kaikki oikeuden pidätetään.","dlgTitle":"Tietoa CKEditorista","moreInfo":"Lisenssitiedot löytyvät kotisivuiltamme:"},"basicstyles":{"bold":"Lihavoitu","italic":"Kursivoitu","strike":"Yliviivattu","subscript":"Alaindeksi","superscript":"Yläindeksi","underline":"Alleviivattu"},"blockquote":{"toolbar":"Lainaus"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Kutista työkalupalkki","toolbarExpand":"Laajenna työkalupalkki","toolbarGroups":{"document":"Dokumentti","clipboard":"Leikepöytä/Kumoa","editing":"Muokkaus","forms":"Lomakkeet","basicstyles":"Perustyylit","paragraph":"Kappale","links":"Linkit","insert":"Lisää","styles":"Tyylit","colors":"Värit","tools":"Työkalut"},"toolbars":"Editorin työkalupalkit"},"clipboard":{"copy":"Kopioi","copyError":"Selaimesi turva-asetukset eivät salli editorin toteuttaa kopioimista. Käytä näppäimistöä kopioimiseen (Ctrl+C).","cut":"Leikkaa","cutError":"Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).","paste":"Liitä","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Leikealue","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Pikavalikon ominaisuudet"},"elementspath":{"eleLabel":"Elementin polku","eleTitle":"%1 elementti"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred dLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['fo']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Trýst ALT og 0 fyri vegleiðing","browseServer":"Ambætarakagi","url":"URL","protocol":"Protokoll","upload":"Send til ambætaran","uploadSubmit":"Send til ambætaran","image":"Myndir","flash":"Flash","form":"Formur","checkbox":"Flugubein","radio":"Radioknøttur","textField":"Tekstteigur","textarea":"Tekstumráði","hiddenField":"Fjaldur teigur","button":"Knøttur","select":"Valskrá","imageButton":"Myndaknøttur","notSet":"<ikki sett>","id":"Id","name":"Navn","langDir":"Tekstkós","langDirLtr":"Frá vinstru til høgru (LTR)","langDirRtl":"Frá høgru til vinstru (RTL)","langCode":"Málkoda","longDescr":"Víðkað URL frágreiðing","cssClass":"Typografi klassar","advisoryTitle":"Vegleiðandi heiti","cssStyle":"Typografi","ok":"Góðkent","cancel":"Avlýs","close":"Lat aftur","preview":"Frumsýn","resize":"Drag fyri at broyta stødd","generalTab":"Generelt","advancedTab":"Fjølbroytt","validateNumberFailed":"Hetta er ikki eitt tal.","confirmNewPage":"Allar ikki goymdar broytingar í hesum innihaldið hvørva. Skal nýggj síða lesast kortini?","confirmCancel":"Nakrir valmøguleikar eru broyttir. Ert tú vísur í, at dialogurin skal latast aftur?","options":"Options","target":"Target","targetNew":"Nýtt vindeyga (_blank)","targetTop":"Vindeyga ovast (_top)","targetSelf":"Sama vindeyga (_self)","targetParent":"Upphavligt vindeyga (_parent)","langDirLTR":"Frá vinstru til høgru (LTR)","langDirRTL":"Frá høgru til vinstru (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Breidd","height":"Hædd","align":"Justering","left":"Vinstra","right":"Høgra","center":"Miðsett","justify":"Javnir tekstkantar","alignLeft":"Vinstrasett","alignRight":"Høgrasett","alignCenter":"Align Center","alignTop":"Ovast","alignMiddle":"Miðja","alignBottom":"Botnur","alignNone":"Eingin","invalidValue":"Invalid value.","invalidHeight":"Hædd má vera eitt tal.","invalidWidth":"Breidd má vera eitt tal.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Virðið sett í \"%1\" feltið má vera eitt positivt tal, við ella uttan gyldugum CSS mátieind (px, %, in, cm, mm, em, ex, pt, ella pc).","invalidHtmlLength":"Virðið sett í \"%1\" feltiðield má vera eitt positivt tal, við ella uttan gyldugum CSS mátieind (px ella %).","invalidInlineStyle":"Virði specifiserað fyri inline style má hava eitt ella fleiri pør (tuples) skrivað sum \"name : value\", hvørt parið sundurskilt við semi-colon.","cssLengthTooltip":"Skriva eitt tal fyri eitt virði í pixels ella eitt tal við gyldigum CSS eind (px, %, in, cm, mm, em, ex, pt, ella pc).","unavailable":"%1<span class=\"cke_accessibility\">, ikki tøkt</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"Um CKEditor 4","moreInfo":"Licens upplýsingar finnast á heimasíðu okkara:"},"basicstyles":{"bold":"Feit skrift","italic":"Skráskrift","strike":"Yvirstrikað","subscript":"Lækkað skrift","superscript":"Hækkað skrift","underline":"Undirstrikað"},"blockquote":{"toolbar":"Blockquote"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Lat Toolbar aftur","toolbarExpand":"Vís Toolbar","toolbarGroups":{"document":"Dokument","clipboard":"Clipboard/Undo","editing":"Editering","forms":"Formar","basicstyles":"Grundleggjandi Styles","paragraph":"Reglubrot","links":"Leinkjur","insert":"Set inn","styles":"Styles","colors":"Litir","tools":"Tól"},"toolbars":"Editor toolbars"},"clipboard":{"copy":"Avrita","copyError":"Trygdaruppseting alnótskagans forðar tekstviðgeranum í at avrita tekstin. Vinarliga nýt knappaborðið til at avrita tekstin (Ctrl/Cmd+C).","cut":"Kvett","cutError":"Trygdaruppseting alnótskagans forðar tekstviðgeranum í at kvetta tekstin. Vinarliga nýt knappaborðið til at kvetta tekstin (Ctrl/Cmd+X).","paste":"Innrita","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Avritingarumráði","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Slóð til elementir","eleTitle":"%1 element"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTPLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['fr-ca']={"editor":"Éditeur de texte enrichi","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Appuyez sur 0 pour de l'aide","browseServer":"Parcourir le serveur","url":"URL","protocol":"Protocole","upload":"Envoyer","uploadSubmit":"Envoyer au serveur","image":"Image","flash":"Animation Flash","form":"Formulaire","checkbox":"Case à cocher","radio":"Bouton radio","textField":"Champ texte","textarea":"Zone de texte","hiddenField":"Champ caché","button":"Bouton","select":"Liste déroulante","imageButton":"Bouton image","notSet":"<Par défaut>","id":"Id","name":"Nom","langDir":"Sens d'écriture","langDirLtr":"De gauche à droite (LTR)","langDirRtl":"De droite à gauche (RTL)","langCode":"Code langue","longDescr":"URL de description longue","cssClass":"Classes CSS","advisoryTitle":"Titre","cssStyle":"Style","ok":"OK","cancel":"Annuler","close":"Fermer","preview":"Aperçu","resize":"Redimensionner","generalTab":"Général","advancedTab":"Avancé","validateNumberFailed":"Cette valeur n'est pas un nombre.","confirmNewPage":"Les changements non sauvegardés seront perdus. Êtes-vous certain de vouloir charger une nouvelle page?","confirmCancel":"Certaines options ont été modifiées. Êtes-vous certain de vouloir fermer?","options":"Options","target":"Cible","targetNew":"Nouvelle fenêtre (_blank)","targetTop":"Fenêtre supérieur (_top)","targetSelf":"Cette fenêtre (_self)","targetParent":"Fenêtre parent (_parent)","langDirLTR":"De gauche à droite (LTR)","langDirRTL":"De droite à gauche (RTL)","styles":"Style","cssClasses":"Classe CSS","width":"Largeur","height":"Hauteur","align":"Alignement","left":"Gauche","right":"Droite","center":"Centré","justify":"Justifié","alignLeft":"Aligner à gauche","alignRight":"Aligner à Droite","alignCenter":"Align Center","alignTop":"Haut","alignMiddle":"Milieu","alignBottom":"Bas","alignNone":"None","invalidValue":"Valeur invalide.","invalidHeight":"La hauteur doit être un nombre.","invalidWidth":"La largeur doit être un nombre.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"La valeur spécifiée pour le champ \"%1\" doit être un nombre positif avec ou sans unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","invalidHtmlLength":"La valeur spécifiée pour le champ \"%1\" doit être un nombre positif avec ou sans unité de mesure HTML valide (px ou %).","invalidInlineStyle":"La valeur spécifiée pour le style intégré doit être composée d'un ou plusieurs couples de valeur au format \"nom : valeur\", separés par des points-virgules.","cssLengthTooltip":"Entrer un nombre pour la valeur en pixel ou un nombre avec une unité CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, indisponible</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. Tous droits réservés.","dlgTitle":"À propos de CKEditor 4","moreInfo":"Pour les informations de licence, consulter notre site internet:"},"basicstyles":{"bold":"Gras","italic":"Italique","strike":"Barré","subscript":"Indice","superscript":"Exposant","underline":"Souligné"},"blockquote":{"toolbar":"Citation"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Enrouler la barre d'outils","toolbarExpand":"Dérouler la barre d'outils","toolbarGroups":{"document":"Document","clipboard":"Presse papier/Annuler","editing":"Édition","forms":"Formulaires","basicstyles":"Styles de base","paragraph":"Paragraphe","links":"Liens","insert":"Insérer","styles":"Styles","colors":"Couleurs","tools":"Outils"},"toolbars":"Barre d'outils de l'éditeur"},"clipboard":{"copy":"Copier","copyError":"Les paramètres de sécurité de votre navigateur empêchent l'éditeur de copier automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl/Cmd+C).","cut":"Couper","cutError":"Les paramètres de sécurité de votre navigateur empêchent l'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl/Cmd+X).","paste":"Coller","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Coller la zone","pasteMsg":"Paste your content inside the area below and press OK."},"contextmenu":{"options":"Options du menu contextuel"},"elementspath":{"eleLabel":"Chemin d'éléments","eleTitle":"element %1"},"filetools":{"loadError":"ELine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['fr']={"editor":"Éditeur de texte enrichi","editorPanel":"Tableau de bord de l'éditeur de texte enrichi","common":{"editorHelp":"Utilisez le raccourci Alt-0 pour obtenir de l'aide","browseServer":"Parcourir le serveur","url":"URL","protocol":"Protocole","upload":"Télécharger","uploadSubmit":"Envoyer sur le serveur","image":"Image","flash":"Flash","form":"Formulaire","checkbox":"Case à cocher","radio":"Bouton radio","textField":"Champ texte","textarea":"Zone de texte","hiddenField":"Champ invisible","button":"Bouton","select":"Liste déroulante","imageButton":"Bouton avec image","notSet":"<indéfini>","id":"ID","name":"Nom","langDir":"Sens d'écriture","langDirLtr":"Gauche à droite (LTR)","langDirRtl":"Droite à gauche (RTL)","langCode":"Code de langue","longDescr":"URL de description longue","cssClass":"Classes de style","advisoryTitle":"Infobulle","cssStyle":"Style","ok":"OK","cancel":"Annuler","close":"Fermer","preview":"Aperçu","resize":"Redimensionner","generalTab":"Général","advancedTab":"Avancé","validateNumberFailed":"Cette valeur n'est pas un nombre.","confirmNewPage":"Les changements non sauvegardés seront perdus. Êtes-vous sûr de vouloir charger une nouvelle page ?","confirmCancel":"Certaines options ont été modifiées. Êtes-vous sûr de vouloir fermer ?","options":"Options","target":"Cible","targetNew":"Nouvelle fenêtre (_blank)","targetTop":"Fenêtre supérieure (_top)","targetSelf":"Même fenêtre (_self)","targetParent":"Fenêtre parent (_parent)","langDirLTR":"Gauche à droite (LTR)","langDirRTL":"Droite à gauche (RTL)","styles":"Style","cssClasses":"Classes de style","width":"Largeur","height":"Hauteur","align":"Alignement","left":"Gauche","right":"Droite","center":"Centrer","justify":"Justifier","alignLeft":"Aligner à gauche","alignRight":"Aligner à droite","alignCenter":"Aligner au centre","alignTop":"Haut","alignMiddle":"Milieu","alignBottom":"Bas","alignNone":"Aucun","invalidValue":"Valeur invalide.","invalidHeight":"La hauteur doit être un nombre.","invalidWidth":"La largeur doit être un nombre.","invalidLength":"La valeur de \"%1\" doit être un nombre positif avec ou sans unité de mesure (%2).","invalidCssLength":"La valeur spécifiée pour le champ « %1 » doit être un nombre positif avec ou sans unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","invalidHtmlLength":"La valeur spécifiée pour le champ « %1 » doit être un nombre positif avec ou sans unité de mesure HTML valide (px ou %).","invalidInlineStyle":"La valeur spécifiée pour le style en ligne doit être composée d'un ou plusieurs couples au format « nom : valeur », séparés par des points-virgules.","cssLengthTooltip":"Entrer un nombre pour une valeur en pixels ou un nombre avec une unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, indisponible</span>","keyboard":{"8":"Retour arrière","13":"Entrée","16":"Majuscule","17":"Ctrl","18":"Alt","32":"Espace","35":"Fin","36":"Origine","46":"Supprimer","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Commande"},"keyboardShortcut":"Raccourci clavier","optionDefault":"Par défaut"},"about":{"copy":"Copyright © $1. Tous droits réservés.","dlgTitle":"À propos de CKEditor 4","moreInfo":"Pour les informations de licence, veuillez visiter notre site web :"},"basicstyles":{"bold":"Gras","italic":"Italique","strike":"Barré","subscript":"Indice","superscript":"Exposant","underline":"Souligné"},"blockquote":{"toolbar":"Citation"},"notification":{"closed":"Notification fermée."},"toolbar":{"toolbarCollapse":"Enrouler la barre d'outils","toolbarExpand":"Dérouler la barre d'outils","toolbarGroups":{"document":"Document","clipboard":"Presse-papier/Défaire","editing":"Édition","forms":"Formulaires","basicstyles":"Styles de base","paragraph":"Paragraphe","links":"Liens","insert":"Insérer","styles":"Styles","colors":"Couleurs","tools":"Outils"},"toolbars":"Barres d'outils de l'éditeur"},"clipboard":{"copy":"Copier","copyError":"Les paramètres de sécurité de votre navigateur n'autorisent pas l'éditeur à exécuter automatiquement l'opération « Copier ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+C).","cut":"Couper","cutError":"Les paramètres de sécurité de votre navigateur n'autorisent pas l'éditeur à exécuter automatiquement l'opération « Couper ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+X).","paste":"Coller","pasteNotification":"Utilisez le raccourci %1 pour coller. Votre navigateur n'accepte pas de coller à l'aide du bouton ou du menu contextuel.","pasteArea":"Coller la zone","pasteMsg":"Collez votre contenu dans la zone de saisie ci-dessouLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['gl']={"editor":"Editor de texto mellorado","editorPanel":"Panel do editor de texto mellorado","common":{"editorHelp":"Prema ALT 0 para obter axuda","browseServer":"Examinar o servidor","url":"URL","protocol":"Protocolo","upload":"Enviar","uploadSubmit":"Enviar ao servidor","image":"Imaxe","flash":"Flash","form":"Formulario","checkbox":"Caixa de selección","radio":"Botón de opción","textField":"Campo de texto","textarea":"Área de texto","hiddenField":"Campo agochado","button":"Botón","select":"Campo de selección","imageButton":"Botón de imaxe","notSet":"<sen estabelecer>","id":"ID","name":"Nome","langDir":"Dirección de escritura do idioma","langDirLtr":"Esquerda a dereita (LTR)","langDirRtl":"Dereita a esquerda (RTL)","langCode":"Código do idioma","longDescr":"Descrición completa do URL","cssClass":"Clases da folla de estilos","advisoryTitle":"Título","cssStyle":"Estilo","ok":"Aceptar","cancel":"Cancelar","close":"Pechar","preview":"Vista previa","resize":"Redimensionar","generalTab":"Xeral","advancedTab":"Avanzado","validateNumberFailed":"Este valor non é un número.","confirmNewPage":"Calquera cambio que non gardara neste contido perderase.\r\nConfirma que quere cargar unha páxina nova?","confirmCancel":"Algunhas das opcións foron cambiadas.\r\nConfirma que quere pechar o diálogo?","options":"Opcións","target":"Destino","targetNew":"Nova xanela (_blank)","targetTop":"Xanela principal (_top)","targetSelf":"Mesma xanela (_self)","targetParent":"Xanela superior (_parent)","langDirLTR":"Esquerda a dereita (LTR)","langDirRTL":"Dereita a esquerda (RTL)","styles":"Estilo","cssClasses":"Clases da folla de estilos","width":"Largo","height":"Alto","align":"Aliñamento","left":"Esquerda","right":"Dereita","center":"Centro","justify":"Xustificado","alignLeft":"Aliñar á esquerda","alignRight":"Aliñar á dereita","alignCenter":"Aliñar ao centro","alignTop":"Arriba","alignMiddle":"Centro","alignBottom":"Abaixo","alignNone":"Ningún","invalidValue":"Valor incorrecto.","invalidHeight":"O alto debe ser un número.","invalidWidth":"O largo debe ser un número.","invalidLength":"O valor especificado para o campo «%1» debe ser un número positivo con ou sen unha unidade de medida correcta (%2).","invalidCssLength":"O valor especificado para o campo «%1» debe ser un número positivo con ou sen unha unidade de medida CSS correcta (px, %, in, cm, mm, em, ex, pt, ou pc).","invalidHtmlLength":"O valor especificado para o campo «%1» debe ser un número positivo con ou sen unha unidade de medida HTML correcta (px ou %).","invalidInlineStyle":"O valor especificado no estilo en liña debe consistir nunha ou máis tuplas co formato «nome : valor», separadas por punto e coma.","cssLengthTooltip":"Escriba un número para o valor en píxeles ou un número cunha unidade CSS correcta (px, %, in, cm, mm, em, ex, pt, ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, non dispoñíbel</span>","keyboard":{"8":"Ir atrás","13":"Intro","16":"Maiús","17":"Ctrl","18":"Alt","32":"Espazo","35":"Fin","36":"Inicio","46":"Supr","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Orde"},"keyboardShortcut":"Atallo de teclado","optionDefault":"Predeterminado"},"about":{"copy":"Copyright © $1. Todos os dereitos reservados.","dlgTitle":"Sobre o CKEditor 4","moreInfo":"Para obter información sobre a licenza, visite o noso sitio web:"},"basicstyles":{"bold":"Negra","italic":"Cursiva","strike":"Riscado","subscript":"Subíndice","superscript":"Superíndice","underline":"Subliñado"},"blockquote":{"toolbar":"Cita"},"notification":{"closed":"Notificación pechada."},"toolbar":{"toolbarCollapse":"Contraer a barra de ferramentas","toolbarExpand":"Expandir a barra de ferramentas","toolbarGroups":{"document":"Documento","clipboard":"Portapapeis/desfacer","editing":"Edición","forms":"Formularios","basicstyles":"Estilos básicos","paragraph":"Paragrafo","links":"Ligazóns","insert":"Inserir","styles":"Estilos","colors":"Cores","tools":"Ferramentas"},"toolbars":"Barras de ferramentas do editor"},"clipboard":{"copy":"Copiar","copyError":"Os axustes de seguranza do seu navegador non permiten que o editor realice automaticamente as tarefas de copia. Use o teclado para iso (Ctrl/Cmd+C).","cut":"Cortar","cutError":"Os axustes de seguranza do seu navegador non permiten que o editor realice automaticamente as tarefas de corte. Use o teclado para iso (Ctrl/Cmd+X).","paste":"Pegar","pasteNotification":"Prema %1 para pegar. O seu navegador non admite pegar co botón da barra de ferramentas ou coa opción do menú contextual.","pasteArea":"Zona de pegado","pasteMsg":"Pegue o contido dentro da área de abaixo e prema Aceptar."},"contextmenu":{"options":"Opcións do menú contextual"},"elemenLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['gu']={"editor":"રીચ ટેક્ષ્ત્ એડીટર","editorPanel":"વધુ વિકલ્પ વાળુ એડિટર","common":{"editorHelp":"મદદ માટ ALT 0 દબાવો","browseServer":"સર્વર બ્રાઉઝ કરો","url":"URL","protocol":"પ્રોટોકૉલ","upload":"અપલોડ","uploadSubmit":"આ સર્વરને મોકલવું","image":"ચિત્ર","flash":"ફ્લૅશ","form":"ફૉર્મ/પત્રક","checkbox":"ચેક બોક્સ","radio":"રેડિઓ બટન","textField":"ટેક્સ્ટ ફીલ્ડ, શબ્દ ક્ષેત્ર","textarea":"ટેક્સ્ટ એરિઆ, શબ્દ વિસ્તાર","hiddenField":"ગુપ્ત ક્ષેત્ર","button":"બટન","select":"પસંદગી ક્ષેત્ર","imageButton":"ચિત્ર બટન","notSet":"<સેટ નથી>","id":"Id","name":"નામ","langDir":"ભાષા લેખવાની પદ્ધતિ","langDirLtr":"ડાબે થી જમણે (LTR)","langDirRtl":"જમણે થી ડાબે (RTL)","langCode":"ભાષા કોડ","longDescr":"વધારે માહિતી માટે URL","cssClass":"સ્ટાઇલ-શીટ ક્લાસ","advisoryTitle":"મુખ્ય મથાળું","cssStyle":"સ્ટાઇલ","ok":"ઠીક છે","cancel":"રદ કરવું","close":"બંધ કરવું","preview":"જોવું","resize":"ખેંચી ને યોગ્ય કરવું","generalTab":"જનરલ","advancedTab":"અડ્વાન્સડ","validateNumberFailed":"આ રકમ આકડો નથી.","confirmNewPage":"સવે કાર્ય વગરનું ફકરો ખોવાઈ જશે. તમને ખાતરી છે કે તમને નવું પાનું ખોલવું છે?","confirmCancel":"ઘણા વિકલ્પો બદલાયા છે. તમારે આ બોક્ષ્ બંધ કરવું છે?","options":"વિકલ્પો","target":"લક્ષ્ય","targetNew":"નવી વિન્ડો (_blank)","targetTop":"ઉપરની વિન્ડો (_top)","targetSelf":"એજ વિન્ડો (_self)","targetParent":"પેરનટ વિન્ડો (_parent)","langDirLTR":"ડાબે થી જમણે (LTR)","langDirRTL":"જમણે થી ડાબે (RTL)","styles":"શૈલી","cssClasses":"શૈલી કલાસીસ","width":"પહોળાઈ","height":"ઊંચાઈ","align":"લાઇનદોરીમાં ગોઠવવું","left":"ડાબી બાજુ ગોઠવવું","right":"જમણી","center":"મધ્ય સેન્ટર","justify":"બ્લૉક, અંતરાય જસ્ટિફાઇ","alignLeft":"ડાબી બાજુએ/બાજુ તરફ","alignRight":"જમણી બાજુએ/બાજુ તરફ","alignCenter":"Align Center","alignTop":"ઉપર","alignMiddle":"વચ્ચે","alignBottom":"નીચે","alignNone":"કઇ નહી","invalidValue":"અનુચિત મૂલ્ય","invalidHeight":"ઉંચાઈ એક આંકડો હોવો જોઈએ.","invalidWidth":"પોહળ ઈ એક આંકડો હોવો જોઈએ.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"\"%1\" ની વેલ્યુ એક પોસીટીવ આંકડો હોવો જોઈએ અથવા CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc) વગર.","invalidHtmlLength":"\"%1\" ની વેલ્યુ એક પોસીટીવ આંકડો હોવો જોઈએ અથવા HTML measurement unit (px or %) વગર.","invalidInlineStyle":"ઈનલાઈન સ્ટાઈલ ની વેલ્યુ \"name : value\" ના ફોર્મેટ માં હોવી જોઈએ, વચ્ચે સેમી-કોલોન જોઈએ.","cssLengthTooltip":"પિક્ષ્લ્ નો આંકડો CSS unit (px, %, in, cm, mm, em, ex, pt, or pc) માં નાખો.","unavailable":"%1<span class=\"cke_accessibility\">, નથી મળતું</span>","keyboard":{"8":"Backspace કી","13":"Enter કી","16":"Shift કી","17":"Ctrl કી","18":"Alt કી","32":"Space કી","35":"End કી","36":"Home કી","46":"Delete કી","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command કી"},"keyboardShortcut":"કીબોર્ડ શૉર્ટકટ","optionDefault":"Default"},"about":{"copy":"કોપીરાઈટ ©Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['he']={"editor":"עורך טקסט עשיר","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"לחץ אלט ALT + 0 לעזרה","browseServer":"סייר השרת","url":"כתובת (URL)","protocol":"פרוטוקול","upload":"העלאה","uploadSubmit":"שליחה לשרת","image":"תמונה","flash":"פלאש","form":"טופס","checkbox":"תיבת סימון","radio":"לחצן אפשרויות","textField":"שדה טקסט","textarea":"איזור טקסט","hiddenField":"שדה חבוי","button":"כפתור","select":"שדה בחירה","imageButton":"כפתור תמונה","notSet":"<לא נקבע>","id":"זיהוי (ID)","name":"שם","langDir":"כיוון שפה","langDirLtr":"שמאל לימין (LTR)","langDirRtl":"ימין לשמאל (RTL)","langCode":"קוד שפה","longDescr":"קישור לתיאור מפורט","cssClass":"מחלקת עיצוב (CSS Class)","advisoryTitle":"כותרת מוצעת","cssStyle":"סגנון","ok":"אישור","cancel":"ביטול","close":"סגירה","preview":"תצוגה מקדימה","resize":"יש לגרור בכדי לשנות את הגודל","generalTab":"כללי","advancedTab":"אפשרויות מתקדמות","validateNumberFailed":"הערך חייב להיות מספרי.","confirmNewPage":"כל השינויים שלא נשמרו יאבדו. האם להעלות דף חדש?","confirmCancel":"חלק מהאפשרויות שונו, האם לסגור את הדיאלוג?","options":"אפשרויות","target":"מטרה","targetNew":"חלון חדש (_blank)","targetTop":"החלון העליון ביותר (_top)","targetSelf":"אותו חלון (_self)","targetParent":"חלון האב (_parent)","langDirLTR":"שמאל לימין (LTR)","langDirRTL":"ימין לשמאל (RTL)","styles":"סגנון","cssClasses":"מחלקות גליונות סגנון","width":"רוחב","height":"גובה","align":"יישור","left":"לשמאל","right":"לימין","center":"מרכז","justify":"יישור לשוליים","alignLeft":"יישור לשמאל","alignRight":"יישור לימין","alignCenter":"Align Center","alignTop":"למעלה","alignMiddle":"לאמצע","alignBottom":"לתחתית","alignNone":"None","invalidValue":"ערך לא חוקי.","invalidHeight":"הגובה חייב להיות מספר.","invalidWidth":"הרוחב חייב להיות מספר.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"הערך שצוין לשדה \"%1\" חייב להיות מספר חיובי עם או ללא יחידת מידה חוקית של CSS (px, %, in, cm, mm, em, ex, pt, או pc).","invalidHtmlLength":"הערך שצוין לשדה \"%1\" חייב להיות מספר חיובי עם או ללא יחידת מידה חוקית של HTML (px או %).","invalidInlineStyle":"הערך שצויין לשדה הסגנון חייב להכיל זוג ערכים אחד או יותר בפורמט \"שם : ערך\", מופרדים על ידי נקודה-פסיק.","cssLengthTooltip":"יש להכניס מספר המייצג פיקסלים או מספר עם יחידת גליונות סגנון תקינה (px, %, in, cm, mm, em, ex, pt, או pc).","unavailable":"%1<span class=\"cke_accessibility\">, לא זמין</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"מחק","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. כל הזכויות שמורות.","dlgTitle":"אודות CKEditor","moreInfo":"למידע נוסף בקרו באתרנו:"},"basicstyles":{"bold":"מודגש","italic":"נטוי","strike":"כתיב מחוק","subscript":"כתיב תחתון","superscript":"כתיב עליון","underline":"קו תחתון"},"blockquote":{"toolbar":"בלוק ציטוט"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"מזעור סרגל כלים","toolbarExpand":"הרחבת סרגל כלים","toolbarGroups":{"document":"מסמך","clipboard":"לוח הגזירים (Clipboard)/צעד אחרון","editing":"עריכה","forms":"טפסים","basicstyles":"עיצוב בסיסי","paragraph":"פסקה","links":"קישורים","insert":"הכנסה","styles":"עיצוב","colors":"צבעים","tools":"כלים"},"toolbars":"סרגלי כלים של העורך"},"clipboard":{"copy":"העתקה","copyError":"הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות העתקה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+C).","cut":"גזירהLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/license
|
||||
*/
|
||||
CKEDITOR.lang['hi']={"editor":"रिच टेक्स्ट एडिटर","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"मदद के लिये ALT 0 दबाए","browseServer":"सर्वर ब्राउज़ करें","url":"URL","protocol":"प्रोटोकॉल","upload":"अपलोड","uploadSubmit":"इसे सर्वर को भेजें","image":"तस्वीर","flash":"फ़्लैश","form":"फ़ॉर्म","checkbox":"चॅक बॉक्स","radio":"रेडिओ बटन","textField":"टेक्स्ट फ़ील्ड","textarea":"टेक्स्ट एरिया","hiddenField":"गुप्त फ़ील्ड","button":"बटन","select":"चुनाव फ़ील्ड","imageButton":"तस्वीर बटन","notSet":"<सॅट नहीं>","id":"Id","name":"नाम","langDir":"भाषा लिखने की दिशा","langDirLtr":"बायें से दायें (LTR)","langDirRtl":"दायें से बायें (RTL)","langCode":"भाषा कोड","longDescr":"अधिक विवरण के लिए URL","cssClass":"स्टाइल-शीट क्लास","advisoryTitle":"परामर्श शीर्शक","cssStyle":"स्टाइल","ok":"ठीक है","cancel":"रद्द करें","close":"Close","preview":"प्रीव्यू","resize":"Resize","generalTab":"सामान्य","advancedTab":"ऍड्वान्स्ड","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"टार्गेट","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"बायें से दायें (LTR)","langDirRTL":"दायें से बायें (RTL)","styles":"स्टाइल","cssClasses":"स्टाइल-शीट क्लास","width":"चौड़ाई","height":"ऊँचाई","align":"ऍलाइन","left":"दायें","right":"दायें","center":"बीच में","justify":"ब्लॉक जस्टीफ़ाई","alignLeft":"बायीं तरफ","alignRight":"दायीं तरफ","alignCenter":"Align Center","alignTop":"ऊपर","alignMiddle":"मध्य","alignBottom":"नीचे","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"},"about":{"copy":"Copyright © $1. All rights reserved.","dlgTitle":"About CKEditor 4","moreInfo":"For licensing information please visit our web site:"},"basicstyles":{"bold":"बोल्ड","italic":"इटैलिक","strike":"स्ट्राइक थ्रू","subscript":"अधोलेख","superscript":"अभिलेख","underline":"रेखांकण"},"blockquote":{"toolbar":"ब्लॉक-कोट"},"notification":{"closed":"Notification closed."},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"एडिटर टूलबार"},"clipboard":{"copy":"कॉपी","copyError":"आपके ब्राआउज़र की सुरक्षLine truncated
|
||||
Loaded 100 of 406 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user