This commit is contained in:
David Anderson 2012-11-16 16:07:12 -08:00
Коммит 6ffc3f8279
171 изменённых файлов: 33197 добавлений и 0 удалений

25
driver/awfy.config Normal file
Просмотреть файл

@ -0,0 +1,25 @@
[main]
testroot = /Users/mozilla/awfy
os = mac10.6
cpu = x64
machine = 4
updateURL = http://www.arewefastyet.com/????
[v8]
source = v8
[jsc]
source = WebKit
[jsci]
source = InterpKit
[tm]
source = mozilla-inbound
[jm]
source = mozilla-inbound
[im]
source = ionmonkey

118
driver/benchmark.py Normal file
Просмотреть файл

@ -0,0 +1,118 @@
# vim: set ts=4 sw=4 tw=99 et:
import re
import os
import sys
import urllib2
import StringIO
import subprocess
import ConfigParser
import submitter
import utils
def ss_v8(shell, env, args):
return run_sunspider('SunSpider', 'v8-v7', 5, shell, env, args)
def ss_SunSpider(shell, env, args):
return run_sunspider('SunSpider', 'sunspider-0.9.1', 20, shell, env, args)
def ss_Kraken(shell, env, args):
return run_sunspider('kraken', 'kraken-1.1', 5, shell, env, args)
def ss_Assorted(shell, env, args):
return run_sunspider('Assorted', 'assorted', 3, shell, env, args)
def run_sunspider(folder, suite, runs, shell, env, args):
with utils.chdir(folder):
return _sunspider(suite, runs, shell, env, args)
def v8_v8(shell, env, args):
with utils.chdir('v8-v7'):
return _v8(shell, env, args)
def _v8(shell, env, args):
full_args = [shell]
if args:
full_args.extend(args)
full_args.append('run.js')
p = subprocess.Popen(full_args, stdout=subprocess.PIPE, env=env)
output = p.communicate()[0]
tests = []
lines = output.splitlines()
for x in lines:
m = re.search("(.+): (\d+)", x)
if m != None:
name = m.group(1)
score = m.group(2)
if name[0:5] == "Score":
name = "__total__"
tests.append({ 'name': name, 'time': score})
print(score + ' - ' + name)
return tests
def _sunspider(suite, runs, shell, env, args):
if args != None:
args = '--args=' + ' '.join(args)
else:
args = ''
if suite == "assorted":
p = subprocess.Popen(["hg", "pull", "-u"], stdout=subprocess.PIPE)
p.communicate()
p = subprocess.Popen(["./sunspider",
"--shell=" + shell,
"--runs=" + str(runs),
"--suite=" + suite,
args],
stdout=subprocess.PIPE,
env=env)
output = p.communicate()[0]
tests = []
lines = output.splitlines()
found = False
for x in lines:
if x == "--------------------------------------------" or \
x == "-----------------------------------------------":
found = True
if x[0:5] == "Total":
m = re.search(":\s+(\d+\.\d+)ms", x)
tests.append({ 'name': '__total__', 'time': m.group(1)})
print(m.group(1) + ' - __total__')
elif found == True and x[0:4] == " ":
m = re.search(" (.+):\s+(\d+\.\d+)ms", x)
if m != None:
tests.append({ 'name': m.group(1), 'time': m.group(2)})
print(m.group(2) + ' - ' + m.group(1))
if found == False:
raise Exception("output marker not found")
return tests
Benchmarks = {
'v8real': v8_v8,
'kraken': ss_Kraken,
'ss': ss_SunSpider,
#'v8': ss_v8,
'misc': ss_Assorted
}
def RunAndSubmitAll(shell, env, args, submitter, mode):
for suite in Benchmarks:
args_ = args
if not args:
args_ = []
print('Running ' + suite + ' under ' + shell + ' ' + ' '.join(args_))
fun = Benchmarks[suite]
try:
tests = fun(shell, env, args)
submitter.AddTests(tests, suite, mode)
except:
pass

138
driver/builders.py Normal file
Просмотреть файл

@ -0,0 +1,138 @@
# vim: set ts=4 sw=4 tw=99 et:
import os
import sys
import puller
import subprocess
from utils import Run
class Engine(object):
def __init__(self, conf):
self.testroot = conf.get('main', 'testroot')
self.cpu = conf.get('main', 'cpu')
def updateAndBuild(self, update, forceRebuild):
pop = os.getcwd()
os.chdir(os.path.join(self.testroot, self.source))
if self.puller == 'svn':
scm = puller.SVN
elif self.puller == 'hg':
scm = puller.HG
shell = self.shell()
if not os.path.isfile(shell):
forceRebuild = True
updated = False
if update:
updated = scm.Update()
if forceRebuild or updated:
try:
os.unlink(shell)
except:
pass
pop2 = os.getcwd()
self.build()
os.chdir(pop2)
updated = True
version = scm.Identify()
if not os.path.isfile(shell):
print(shell)
os.chdir(pop)
raise Exception('could not find shell')
os.chdir(pop)
return [version, updated]
def env(self):
return None
class Nitro(Engine):
def __init__(self, conf):
super(Nitro, self).__init__(conf)
self.puller = 'svn'
self.source = conf.get('jsc', 'source')
self.args = None
self.important = False
self.modes = [
{
'mode': 'jsc',
'args': None
}
]
def env(self):
env = os.environ.copy()
env['DYLD_FRAMEWORK_PATH'] = os.path.abspath(os.path.join('WebKitBuild', 'Release'))
return env
def build(self):
pop = os.getcwd()
os.chdir(os.path.join('Tools', 'Scripts'))
if self.cpu == 'x86':
Run(['/usr/bin/perl', 'build-jsc', '--32-bit'])
else:
Run(['/usr/bin/perl', 'build-jsc'])
os.chdir(pop)
def shell(self):
return os.path.join('WebKitBuild', 'Release', 'jsc')
class V8(Engine):
def __init__(self, conf):
super(V8, self).__init__(conf)
self.puller = 'svn'
self.source = conf.get('v8', 'source')
self.args = ['--expose-gc']
self.important = True
self.modes = [
{
'mode': 'v8',
'args': None
}
]
def build(self):
Run(['make', 'dependencies'])
if self.cpu == 'x64':
Run(['make', 'x64.release'])
elif self.cpu == 'arm':
Run(['make', 'arm.release'])
elif self.cpu == 'x86':
Run(['make', 'ia32.release'])
def shell(self):
if self.cpu == 'x64':
return os.path.join('out', 'x64.release', 'd8')
elif self.cpu == 'arm':
return os.path.join('out', 'arm.release', 'd8')
elif self.cpu == 'x86':
return os.path.join('out', 'ia32.release', 'd8')
class Mozilla(Engine):
def __init__(self, conf):
super(Mozilla, self).__init__(conf)
self.puller = 'hg'
self.source = conf.get('jm', 'source')
self.args = None
self.important = True
self.modes = [
{
'mode': 'ti',
'args': ['-m', '-n', '--no-ion']
},
{
'mode': 'jmim',
'args': ['--ion', '-m', '-n']
}
]
def build(self):
os.system("make -j 3 -C " + os.path.join('js', 'src', 'Opt'))
def shell(self):
return os.path.join('js', 'src', 'Opt', 'js')

63
driver/dostuff.py Normal file
Просмотреть файл

@ -0,0 +1,63 @@
# vim: set ts=4 sw=4 tw=99 et:
import os
import ConfigParser
import submitter
import builders
import sys
import resource
import benchmark
import utils
config = ConfigParser.RawConfigParser()
config.read('awfy.config')
resource.setrlimit(resource.RLIMIT_AS, (-1, -1))
resource.setrlimit(resource.RLIMIT_RSS, (-1, -1))
resource.setrlimit(resource.RLIMIT_DATA, (-1, -1))
# JSC is ilooping...
KnownEngines = [
builders.V8(config),
builders.Mozilla(config),
builders.Nitro(config)
]
Engines = []
MozillaUpdated = False
NumUpdated = 0
for e in KnownEngines:
try:
cset, updated = e.updateAndBuild(True, False)
except:
print('Build failed!')
continue
if cset == None:
continue
if updated and e.important:
NumUpdated += 1
Engines.append([e, cset, updated])
if NumUpdated == 0:
sys.exit(0)
submit = submitter.Submitter(config)
submit.Start()
for entry in Engines:
e = entry[0]
cset = entry[1]
shell = os.path.join(config.get('main', 'testroot'), e.source, e.shell())
env = None
with utils.chdir(os.path.join(config.get('main', 'testroot'), e.source)):
env = e.env()
for m in e.modes:
if e.args:
args = list(e.args)
if m['args']:
args.append(*m['args'])
elif m['args']:
args = list(m['args'])
else:
args = None
submit.AddEngine(m['mode'], cset)
benchmark.RunAndSubmitAll(shell, env, args, submit, m['mode'])
submit.Finish(1)

35
driver/puller.py Normal file
Просмотреть файл

@ -0,0 +1,35 @@
# vim: set ts=4 sw=4 tw=99 et:
import re
import os
import sys
import subprocess
from utils import Run
class HG:
@staticmethod
def Update():
output = Run(['hg', 'pull', '-u'])
return re.search("no changes found", output) == None
@staticmethod
def Identify():
output = Run(['hg', 'id', '-i'])
m = re.match("([0-9a-z]+)\s*", output)
if m == None:
raise Exception('unknown output from hg: ' + output)
return m.group(1)
class SVN:
@staticmethod
def Update():
output = Run(['svn', 'update'])
return re.search("At revision", output) == None
@staticmethod
def Identify():
output = Run(['svn', 'info'])
m = re.search("Revision: ([0-9]+)", output)
if m == None:
raise Exception('unknown output from svn: ' + output)
return m.group(1)

52
driver/submitter.py Normal file
Просмотреть файл

@ -0,0 +1,52 @@
# vim: set ts=4 sw=4 tw=99 et:
import re
import urllib2
class Submitter:
def __init__(self, conf):
self.url = conf.get('main', 'updateURL')
self.cpu = conf.get('main', 'cpu')
self.os = conf.get('main', 'os')
self.machine = conf.get('main', 'machine')
def Start(self):
url = self.url
url += '?run=yes'
url += '&CPU=' + self.cpu
url += '&OS=' + self.os
url += '&MACHINE=' + str(self.machine)
url = urllib2.urlopen(url)
contents = url.read()
m = re.search('id=(\d+)', contents)
if m == None:
raise Exception('Remote error: ' + contents)
self.runID = int(m.group(1))
def AddEngine(self, name, cset):
url = self.url
url += '?run=addEngine'
url += '&runid=' + str(self.runID)
url += '&name=' + name
url += '&cset=' + str(cset)
urllib2.urlopen(url)
def AddTests(self, tests, suite, mode):
for test in tests:
self.SubmitTest(test['name'], suite, mode, test['time'])
def SubmitTest(self, name, suite, mode, time):
url = self.url
url += '?name=' + name
url += '&run=' + str(self.runID)
url += '&suite=' + suite
url += '&mode=' + mode
url += '&time=' + str(time)
urllib2.urlopen(url)
def Finish(self, status):
url = self.url
url += '?run=finish'
url += '&status=' + str(status)
url += '&runid=' + str(self.runID)
urllib2.urlopen(url)

26
driver/utils.py Normal file
Просмотреть файл

@ -0,0 +1,26 @@
# vim: set ts=4 sw=4 tw=99 et:
import os
import subprocess
class FolderChanger:
def __init__(self, folder):
self.old = os.getcwd()
self.new = folder
def __enter__(self):
os.chdir(self.new)
def __exit__(self, type, value, traceback):
os.chdir(self.old)
def chdir(folder):
return FolderChanger(folder)
def Run(vec):
print(">> Executing in " + os.getcwd())
print(' '.join(vec))
o = subprocess.check_output(vec, stderr=subprocess.STDOUT)
o = o.decode("utf-8")
print(o)
return o

Просмотреть файл

@ -0,0 +1,59 @@
<?php
require_once("internals.php");
init_database();
if (isset($_GET['run']) && $_GET['run'] == 'yes') {
$CPU = mysql_real_escape_string(GET_string('CPU'));
$OS = mysql_real_escape_string(GET_string('OS'));
$MACHINE = GET_int('MACHINE');
$CSET = mysql_real_escape_string(GET_string('CSET'));
mysql_query("INSERT INTO fast_run (cpu, os, machine, stamp, cset)
VALUES
('$CPU', '$OS', $MACHINE, UNIX_TIMESTAMP(), '$CSET')")
or die("ERROR: " . mysql_error());
print("id=" . mysql_insert_id());
} else if (isset($_GET['run']) && $_GET['run'] == 'finish') {
$runid = GET_int('runid');
$status = GET_int('status');
if (isset($_GET['error']))
$error = '\'' . mysql_real_escape_string(GET_string('error')) . '\'';
else
$error = 'NULL';
mysql_query("UPDATE fast_run
SET status = $status,
error = $error
WHERE id = $runid")
or die("ERROR: " . mysql_error());
} else if (isset($_GET['run']) && $_GET['run'] == 'addEngine') {
$runid = GET_int('runid');
$mode_id = find_mode(GET_string('name'));
$cset = mysql_real_escape_string(GET_string('cset'));
mysql_query("INSERT INTO awfy_build
(run_id, mode_id, cset)
VALUES
($runid, $mode_id, '$cset')")
or die("ERROR: " . mysql_error());
} else {
$name = mysql_real_escape_string(GET_string('name'));
$time = mysql_real_escape_string(GET_string('time'));
$suite_id = find_suite(GET_string('suite'));
$mode_id = find_mode(GET_string('mode'));
$run = GET_int('run');
if ($name == '__total__') {
mysql_query("INSERT INTO awfy_score
(run_id, suite_id, mode_id, score)
VALUES
($run, $suite_id, $mode_id, $time)")
or die("ERROR: " . mysql_error());
} else {
mysql_query("INSERT INTO awfy_breakdown
(run_id, suite_id, mode_id, test, score)
VALUES
($run, $suite_id, $mode_id, '$name', $time)")
or die("ERROR: " . mysql_error());
}
}
?>

Просмотреть файл

@ -0,0 +1,62 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AWFY - Frequently Asked Questions</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h1>Frequently Asked Questions</h1>
<ol id="faq">
<li>
<p>What's this site?</p>
<p>This site tracks the performance of popular JavaScript engines.</p>
</li>
<li>
<p>What versions are you testing with?</p>
<p>Each test run checks out a copy of the latest source code for each vendor it's testing. This means we're testing the latest, greatest, unstable, bleeding-edge versions of browsers' JS engines. The scores here may not represent what you see in stable releases.</p>
</li>
<li>
<p>Who's behind it? Is Mozilla?</p>
<p>This site is maintained by Mozilla's JavaScript team.</p>
Special thanks to wx24 for the new layout, and Michael Clackler for the UI improvements such as hover-tip deltas. Awesome!
</li>
<li>
<p>Why does the v8 benchmark go down, instead of up?</p>
<p>The v8 benchmark produces a score, not raw time. We inverted the graph so they all look like "lower is better".</p>
</li>
<li>
<p>Why do some changesets appear multiple times?</p>
<p>The graphs update on every v8 or tracemonkey check-in, roughly, so if one updates but not the other, the same changeset can be tested twice.</p>
</li>
<li>
<p>Why isn't Opera/IE/something here?</p>
<p>Right now, the performance tests are run on a Mac, which means no IE. Also the tests rely on a "shell" JS engine that runs in a command line. It doesn't test browsers. We'll change that, eventually.</p>
</li>
<li>
<p>What are the axes?</p>
<p>The Y axis is time to benchmark completion. Lower is better. The X axis represents test runs, chronologically. The left-most run is the oldest, the right-most run is the latest.</p>
</li>
<li>
<p>What are the graphs?</p>
<p>The top left-hand graph is Mozilla's Kraken benchmark. The top right-hand graph is Apple's SunSpider benchmark. The bottom graph is Google's V8 benchmark suite.</p>
</li>
<li>
<p>What do the hover tips mean?</p>
<p>"Time" is...time. "Source" is where we got the engine from. "Tested" is when we downloaded the engine, compiled, and tested it. "Rev" is the unique point in the engine's revision history we tested. These numbers/strings are for developers to see which changes happened in between points in the graph.</p>
</li>
<li>
<p>What runs the tests?</p>
<p>A mac-mini.</p>
</li>
<li>
<p>What's ARM?</p>
<p>ARM is the CPU present in many embedded devices, like smartphones. We're interested in this for mobile Firefox.</p>
</li>
<li>
<p>Is this open source?</p>
<p>It's not very interesting (or good), but yes: <a href="http://hg.mozilla.org/users/danderson_mozilla.com/awfy">click here</a></p>
</li>
</ol>
</body>
</html>

Просмотреть файл

@ -0,0 +1,230 @@
<?php
date_default_timezone_set('UTC');
/* vim: set ts=4 sw=4 tw=99 et: */
require_once("internals.php");
init_database();
global $MACHINE;
$MACHINE = 5;
if (isset($_GET['machine']))
$MACHINE = intval($_GET['machine']);
$smarty = new_smarty();
$smarty->assign('arewefastyet', 'NO.');
$smarty->assign('MACHINE', $MACHINE);
Everything($smarty);
$smarty->display('arewefastyet.tpl');
function GetStat($suite, $mode)
{
global $MACHINE;
$query = "SELECT id FROM `fast_run`
WHERE status = 1 AND
machine = $MACHINE
ORDER BY stamp DESC LIMIT 1";
$res = mysql_query($query) or die("ERROR: " . mysql_error() . "\n");
if (!mysql_num_rows($res))
die("no data\n");
$top = mysql_fetch_array($res);
$top = $top[0];
$query = "SELECT SUM(time_ms) FROM fast_test
WHERE suite = '$suite' AND
mode = '$mode' AND
machine = $MACHINE
run = $top";
$res = mysql_query($query);
$data = mysql_fetch_array($res);
return number_format($data[0], 0);
}
function &BuildLines(&$stats, $modes, &$runIds, $suite)
{
$MODE_NAMES = array('j' => 'tracer',
'm' => 'jmnotrc',
'v8' => 'v8',
'jsc' => 'nitro',
'mooi' => 'mooi',
'moom' => 'moom',
'mooj' => 'mooj');
$lines = array();
for ($i = 0; $i < count($modes); $i++) {
$mode = $modes[$i];
$lines[$mode] = '[';
$counter = 0;
for ($j = count($runIds) - 1; $j >= 0; $j--) {
$runId = $runIds[$j];
if (isset($stats[$runId][$suite][$mode]))
$amount = $stats[$runId][$suite][$mode];
else
$amount = 'null';
$lines[$mode] .= '[' . $counter . ',' .
$amount .
']';
if ($j != 0)
$lines[$mode] .= ',';
$counter++;
}
$lines[$mode] .= ']';
}
$nlines = array();
for ($i = 0; $i < count($modes); $i++) {
$mode = $modes[$i];
$nlines[] = array('name' => $MODE_NAMES[$mode],
'data' => $lines[$mode]);
}
return $nlines;
}
function Everything(&$smarty)
{
global $MACHINE;
$runs = FindRuns(32);
/* Find runs that failed. */
for ($i = 0; $i < count($runs); $i++) {
$run = $runs[$i];
if ($run['status'] != 1) {
$smarty->assign('runError', $run);
break;
}
}
$runIds = array();
$runTimes = array();
for ($i = 0; $i < count($runs); $i++) {
if ($runs[$i]['status'] != 1)
continue;
$runIds[] = $runs[$i]['id'];
$runTimes[] = date("M j, Y", $runs[$i]['stamp']);
}
$runTimes = array_reverse($runTimes);
if (count($runIds) == 0) {
die("oh no what are you doing");
}
$idstr = implode(",", $runIds);
$query = "SELECT run, name, time_ms, suite, mode
FROM fast_test
WHERE run IN ($idstr)";
$result = mysql_query($query) or die("error: " . mysql_error());
$suite_stats = array();
while (($row = mysql_fetch_array($result)) !== FALSE) {
$runId = $row['run'];
$name = $row['name'];
$time = $row['time_ms'];
$suite = $row['suite'];
$mode = $row['mode'];
if ($mode == '')
$mode = 'i';
if (!isset($suite_stats[$runId][$suite][$mode]))
$suite_stats[$runId][$suite][$mode] = floatval($time);
else
$suite_stats[$runId][$suite][$mode] += floatval($time);
}
$query = "SELECT run, name, cset FROM fast_engine
WHERE run IN ($idstr)";
$result = mysql_query($query) or die("error: " . mysql_error());
$builds = array();
while (($row = mysql_fetch_array($result)) !== FALSE) {
$runId = $row['run'];
$builds[$runId] = array('engine' => $row['name'], 'cset' => $row['cset']);
}
$MIDS = array(3 => array('j', 'v8'),
4 => array('v8', 'jsc', 'mooj', 'j'),
5 => array('v8', 'jsc', 'mooj', 'j'),
6 => array('j', 'moom', 'mooj', 'v8'),
7 => array('j', 'moom', 'mooj', 'v8')
);
/* Build the line graph data sets. */
$self_ss = BuildLines($suite_stats, $MIDS[$MACHINE], $runIds, 'ss');
$self_v8 = BuildLines($suite_stats, $MIDS[$MACHINE], $runIds, 'v8');
$smarty->assign('self_ss', $self_ss);
$smarty->assign('self_v8', $self_v8);
/* Now, in the same order, we want build information about each engine. */
$query = "SELECT fr.id, fe.name, fe.cset
FROM fast_engine fe
JOIN fast_run fr
ON fe.run = fr.id
WHERE fr.id IN ($idstr)
ORDER BY fr.id ASC";
$query = mysql_query($query);
if (!$query)
die('error: ' . mysql_error());
/* Prep the mapping of engine names and runs to builds. */
$engines = array('jm', 'tm', 'v8', 'jsc', 'jsci', 'moo');
$engineStrings = array();
for ($i = 0; $i < count($engines); $i++)
$engineStrings[$engines[$i]] = array();
/* Map engine names and run IDs to builds. */
while (($data = mysql_fetch_array($query)) !== FALSE)
$engineStrings[$data[1]][$data[0]] = "'" . $data[2] . "'";
/* Please agree with me that this is hideous. Why aren't I using Python. */
$engineBuilds = array();
for ($i = 0; $i < count($engines); $i++) {
$engine = $engines[$i];
$newvec = array();
for ($j = count($runIds) - 1; $j >= 0; $j--) {
$run = $runIds[$j];
if (isset($engineStrings[$engine][$run])) {
$newvec[] = $engineStrings[$engine][$run];
} else {
$newvec[] = "null";
}
}
$engineBuilds[$engine] = implode(',', $newvec);
}
$smarty->assign('engineBuilds', $engineBuilds);
$smarty->assign('runTimes', $runTimes);
$EMAP = array('j' => 'tm',
'mj' => 'tm',
'v8' => 'v8',
'jsc' => 'jsc',
'moom' => 'tm',
'mooj' => 'tm');
/* Give a mapping from seriesIndex to engine name. */
$engineMapping = array();
for ($i = 0; $i < count($MIDS[$MACHINE]); $i++) {
$engineMapping[] = "'" . $EMAP[$MIDS[$MACHINE][$i]] . "'";
}
$engineMapping = '[' . implode(',', $engineMapping) . ']';
$smarty->assign('engineMapping', $engineMapping);
}
function FindRuns($num)
{
global $MACHINE;
$query = "SELECT id, stamp, cset, status, error
FROM fast_run
WHERE machine = $MACHINE
ORDER BY stamp DESC
LIMIT $num";
$result = mysql_query($query) or die("error");
$runs = array();
while (($row = mysql_fetch_array($result)) !== FALSE)
$runs[] = $row;
return $runs;
}
?>

Просмотреть файл

@ -0,0 +1,254 @@
<?php
/* vim: set ts=4 sw=4 tw=99 et: */
require_once("internals.php");
init_database();
global $MACHINE;
$MACHINE = 5;
if (isset($_GET['machine']))
$MACHINE = intval($_GET['machine']);
global $STOP_DATE;
$STOP_DATE = FALSE;
if (isset($_GET['stopDate']))
$STOP_DATE = intval($_GET['stopDate']);
$smarty = new_smarty();
$smarty->assign('arewefastyet', 'NO.');
$smarty->assign('MACHINE', $MACHINE);
$TEST_LIST = array('ss-3bit-bits-in-byte',
'ss-aes',
'ss-base64',
'ss-binary-trees',
'ss-bits-in-byte',
'ss-bitwise-and',
'ss-cordic',
'v8-crypto',
'ss-cube',
'v8-deltablue',
'ss-dna',
'v8-earley-boyer',
'ss-fannkuch',
'ss-fasta',
'ss-format-tofte',
'ss-format-xparb',
'ss-md5',
'ss-morph',
'ss-nbody',
'ss-nsieve',
'ss-nsieve-bits',
'ss-partial-sums',
'ss-raytrace',
'v8-raytrace',
'ss-recursive',
'v8-regexp',
'v8-richards',
'ss-sha1',
'ss-spectral-norm',
'v8-splay',
'ss-tagcloud',
'ss-unpack-code',
'ss-validate-input');
Everything($smarty);
$smarty->display('individual.tpl');
function &BuildLines(&$stats, $modes, &$runIds, $test)
{
$MODE_NAMES = array('j' => 'tracer',
'm' => 'jmnotrc',
'v8' => 'v8',
'jsc' => 'nitro',
'moom' => 'moom',
'mooj' => 'mooj');
$lines = array();
for ($i = 0; $i < count($modes); $i++) {
$mode = $modes[$i];
$lines[$mode] = '[';
$counter = 0;
for ($j = count($runIds) - 1; $j >= 0; $j--) {
$runId = $runIds[$j];
if (isset($stats[$runId][$test][$mode]))
$amount = $stats[$runId][$test][$mode];
else
$amount = 'null';
$lines[$mode] .= '[' . $counter . ',' .
$amount .
']';
if ($j != 0)
$lines[$mode] .= ',';
$counter++;
}
$lines[$mode] .= ']';
}
$nlines = array();
for ($i = 0; $i < count($modes); $i++) {
$mode = $modes[$i];
$nlines[] = array('name' => $MODE_NAMES[$mode],
'data' => $lines[$mode]);
}
return $nlines;
}
function Everything(&$smarty)
{
global $MACHINE;
$runs = FindRuns(70);
/* Find runs that failed. */
for ($i = 0; $i < count($runs); $i++) {
$run = $runs[$i];
if ($run['status'] != 1) {
$smarty->assign('runError', $run);
break;
}
}
$runIds = array();
$runTimes = array();
for ($i = 0; $i < count($runs); $i++) {
if ($runs[$i]['status'] != 1)
continue;
$runIds[] = $runs[$i]['id'];
$runTimes[] = date("M j, Y", $runs[$i]['stamp']);
}
$runTimes = array_reverse($runTimes);
if (count($runIds) == 0) {
die("oh no what are you doing");
}
$idstr = implode(",", $runIds);
$query = "SELECT run, name, time_ms, mode, suite
FROM fast_test
WHERE run IN ($idstr)";
$result = mysql_query($query) or die("error: " . mysql_error());
$suite_stats = array();
while (($row = mysql_fetch_array($result)) !== FALSE) {
$runId = $row['run'];
$name = $row['suite'] . '-' . $row['name'];
$time = $row['time_ms'];
$mode = $row['mode'];
if ($mode == '')
$mode = 'i';
if (!isset($suite_stats[$runId][$name][$mode]))
$suite_stats[$runId][$name][$mode] = floatval($time);
else
$suite_stats[$runId][$name][$mode] += floatval($time);
}
$query = "SELECT run, name, cset FROM fast_engine
WHERE run IN ($idstr)";
$result = mysql_query($query) or die("error: " . mysql_error());
$builds = array();
while (($row = mysql_fetch_array($result)) !== FALSE) {
$runId = $row['run'];
$builds[$runId] = array('engine' => $row['name'], 'cset' => $row['cset']);
}
$MIDS = array(3 => array('j', 'v8'),
4 => array('j', 'v8', 'jsc', 'moom', 'mooj'),
5 => array('j', 'v8', 'jsc', 'moom', 'mooj'),
6 => array('j', 'moom', 'mooj', 'v8'),
7 => array('j', 'moom', 'mooj', 'v8')
);
/* Build the line graph data sets. */
global $TEST_LIST;
$tests = array();
for ($i = 0; $i < count($TEST_LIST); $i++) {
$lines = BuildLines($suite_stats, $MIDS[$MACHINE], $runIds, $TEST_LIST[$i]);
$tests[] = array('lines' => $lines, 'name' => $TEST_LIST[$i]);
}
$smarty->assign('tests', $tests);
/* Now, in the same order, we want build information about each engine. */
$query = "SELECT fr.id, fe.name, fe.cset
FROM fast_engine fe
JOIN fast_run fr
ON fe.run = fr.id
WHERE fr.id IN ($idstr)
ORDER BY fr.id ASC";
$query = mysql_query($query);
if (!$query)
die('error: ' . mysql_error());
/* Prep the mapping of engine names and runs to builds. */
$engines = array('jm', 'tm', 'v8', 'jsc', 'moo');
$engineStrings = array();
for ($i = 0; $i < count($engines); $i++)
$engineStrings[$engines[$i]] = array();
/* Map engine names and run IDs to builds. */
while (($data = mysql_fetch_array($query)) !== FALSE)
$engineStrings[$data[1]][$data[0]] = "'" . $data[2] . "'";
/* Please agree with me that this is hideous. Why aren't I using Python. */
$engineBuilds = array();
for ($i = 0; $i < count($engines); $i++) {
$engine = $engines[$i];
$newvec = array();
for ($j = count($runIds) - 1; $j >= 0; $j--) {
$run = $runIds[$j];
if (isset($engineStrings[$engine][$run])) {
$newvec[] = $engineStrings[$engine][$run];
} else {
$newvec[] = "null";
}
}
$engineBuilds[$engine] = implode(',', $newvec);
}
$smarty->assign('engineBuilds', $engineBuilds);
$smarty->assign('runTimes', $runTimes);
$EMAP = array('j' => 'tm',
'mj' => 'tm',
'v8' => 'v8',
'jsc' => 'jsc',
'moom' => 'tm',
'mooj' => 'tm');
/* Give a mapping from seriesIndex to engine name. */
$engineMapping = array();
for ($i = 0; $i < count($MIDS[$MACHINE]); $i++) {
$engineMapping[] = "'" . $EMAP[$MIDS[$MACHINE][$i]] . "'";
}
$engineMapping = '[' . implode(',', $engineMapping) . ']';
$smarty->assign('engineMapping', $engineMapping);
}
function FindRuns($num)
{
global $MACHINE;
global $STOP_DATE;
if ($STOP_DATE) {
$query = "SELECT id, stamp, cset, status, error
FROM fast_run
WHERE machine = $MACHINE
AND stamp <= $STOP_DATE
ORDER BY stamp DESC
LIMIT $num";
} else {
$query = "SELECT id, stamp, cset, status, error
FROM fast_run
WHERE machine = $MACHINE
ORDER BY stamp DESC
LIMIT $num";
}
$result = mysql_query($query) or die("error");
$runs = array();
while (($row = mysql_fetch_array($result)) !== FALSE)
$runs[] = $row;
return $runs;
}
?>

Просмотреть файл

@ -0,0 +1,75 @@
<?php
// vim: set ts=4 sw=4 tw=99 et:
require_once("smarty/libs/Smarty.class.php");
function init_database()
{
mysql_connect("localhost", "***", "***") or die("ERROR: " . mysql_error());
mysql_select_db("dvander") or die("ERROR: " . mysql_error());
}
function GET_int($name)
{
if (isset($_GET[$name]))
return intval($_GET[$name]);
return 0;
}
function GET_string($name)
{
if (isset($_GET[$name]))
return $_GET[$name];
return "";
}
function new_smarty()
{
$smarty = new Smarty;
$base = '/usr/apache/htdocs';
$smarty->template_dir = $base . '/templates';
$smarty->compile_dir = $base . '/cache_templates';
$smarty->cache_dir = $base . '/cache_stuff';
return $smarty;
}
function find_vendor_of_mode_id($mode_id)
{
$query = "SELECT vendor_id FROM awfy_mode
WHERE id = $mode_id";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1)
return 01;
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function find_mode($mode)
{
$query = "SELECT id FROM awfy_mode
WHERE mode = '" . mysql_real_escape_string($mode) . "'";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1)
return -1;
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function find_suite($suite)
{
$query = "SELECT id FROM awfy_suite
WHERE name = '" . mysql_real_escape_string($suite) . "'";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1)
return -1;
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function awfy_query($query)
{
$result = mysql_query($query) or die(mysql_error());
return $result;
}
?>

Просмотреть файл

@ -0,0 +1,4 @@
internals.php has settings redacted - fill 'em in, under mysql_connect and /usr/apache/htdocs
UPDATED.PHP should be renamed to something random, not very secure i know but this is a hack job.

Просмотреть файл

@ -0,0 +1,41 @@
<?php
/* vim: set ts=4 sw=4 tw=99 et: */
require_once("internals.php");
init_database();
global $MACHINE;
$smarty = new_smarty();
Everything($smarty);
$smarty->display('rss.tpl');
function Everything(&$smarty)
{
$runs = FindRuns(20);
for ($i = 0; $i < count($runs); $i++) {
$runs[$i]['date'] = date("M j, Y H:i", $runs[$i]['stamp']);
}
$smarty->assign('runs', $runs);
}
function FindRuns($num)
{
global $MACHINE;
$query = "SELECT id, stamp, cset, status, error, machine, cpu, os
FROM fast_run
ORDER BY stamp DESC
LIMIT $num";
$result = mysql_query($query) or die("error");
$runs = array();
while (($row = mysql_fetch_array($result)) !== FALSE)
$runs[] = $row;
return $runs;
}
?>

Просмотреть файл

@ -0,0 +1,63 @@
-- phpMyAdmin SQL Dump
-- version 3.1.3
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Apr 23, 2010 at 03:53 AM
-- Server version: 5.1.41
-- PHP Version: 5.2.9
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- Database: `dvander`
--
-- --------------------------------------------------------
--
-- Table structure for table `fast_engine`
--
CREATE TABLE IF NOT EXISTS `fast_engine` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`run` int(10) unsigned NOT NULL,
`name` varchar(32) NOT NULL,
`cset` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
--
-- Table structure for table `fast_run`
--
CREATE TABLE IF NOT EXISTS `fast_run` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cpu` varchar(20) NOT NULL,
`os` varchar(20) NOT NULL,
`machine` int(10) unsigned NOT NULL,
`stamp` int(10) unsigned NOT NULL,
`cset` varchar(160) NOT NULL,
`status` int(11) NOT NULL,
`error` mediumtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
-- --------------------------------------------------------
--
-- Table structure for table `fast_test`
--
CREATE TABLE IF NOT EXISTS `fast_test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`run` int(10) unsigned NOT NULL,
`name` varchar(50) NOT NULL,
`time_ms` float NOT NULL,
`suite` varchar(50) NOT NULL,
`mode` varchar(12) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

Просмотреть файл

@ -0,0 +1,123 @@
body {
background-color:#FFF;
font:.6875em Verdana, Arial, Helvetica, sans-serif;
color:#000;
}
a {
color:#000;
text-decoration:underline;
}
a:hover {
text-decoration:none;
}
h1 {
font-size:2.265em;
font-weight:700;
}
#graph-container {
margin: 0 auto;
width:1040px;
}
.graph, .label {
width:900px;
}
.graph {
height: 350px;
}
.label {
position:relative;
text-align:center;
padding-bottom:5px;
}
#tooltip {
-moz-border-radius:.35em;
-webkit-border-radius:.35em;
background-color:#000;
color:#FFF;
display:none;
opacity:0.8;
padding:.25em;
position:absolute;
}
#tooltip a:link, #tooltip a:active, #tooltip a:visited {
color:#FFF;
text-decoration: underline;
}
#tooltip a:hover {
color:#FFF;
text-decoration: none;
}
.engine-legend {
padding-top:2em;
clear:both;
}
.engine-legend {
text-align:center;
}
#legend1 {
margin-bottom:-1em;
}
#legend2, #links, h1 {
text-align:center;
margin-bottom:1em;
}
.engine-legend li, #links li {
display:inline;
}
.engine-legend li {
border-left:1.2em solid #FFF;
padding-left:.5em;
margin-right:2em;
}
.engine-legend #tracing {
border-color:#FFA451;
}
.engine-legend #jaeger {
border-color:#3E99D7;
}
.engine-legend #jaeger-and-tracing {
border-color:#6f0a93;
}
.engine-legend #google-v8 {
border-color:#4DA74D;
}
.engine-legend #apple-nitro {
border-color:#CF4B4B;
}
.engine-legend #interpreter {
border-color:#737373;
}
.engine-legend #apple-jsci {
border-color:#EF8B8B;
}
.engine-legend #moz-mooi {
border-color:#027364;
}
.engine-legend #moz-moom {
border-color:#000000;
}
#links li {
border-right:1px solid #000;
padding:0 1.265em 0 1em;
}
#links li:last-child {
border:none;
}
#lastUpdate {
float:right;
margin-bottom:1em;
color: gray;
font-size: x-small;
}
#faq {
margin:2em auto;
width:80%;
}
#faq li {
font-weight:700
}
#faq li p:last-child {
font-weight:normal;
}

Просмотреть файл

@ -0,0 +1,127 @@
body {
background-color:#FFF;
font:.6875em Verdana, Arial, Helvetica, sans-serif;
color:#000;
}
a {
color:#000;
text-decoration:underline;
}
a:hover {
text-decoration:none;
}
h1 {
font-size:2.265em;
font-weight:700;
}
#graph-container {
margin: 0 auto;
width:1140px;
}
#sunspider-graph, #v8-graph, #sunspider-label, #v8-label {
width:555px;
float:left;
}
#sunspider-graph, #v8-graph {
height:350px;
}
#v8-graph, #v8-label {
Left:50px;
}
#sunspider-label, #v8-label {
position:relative;
text-align:center;
padding-bottom:5px;
}
#tooltip {
-moz-border-radius:.35em;
-webkit-border-radius:.35em;
background-color:#000;
color:#FFF;
display:none;
opacity:0.8;
padding:.25em;
position:absolute;
}
#tooltip a:link, #tooltip a:active, #tooltip a:visited {
color:#FFF;
text-decoration: underline;
}
#tooltip a:hover {
color:#FFF;
text-decoration: none;
}
.engine-legend {
padding-top:2em;
clear:both;
}
.engine-legend {
text-align:center;
}
#legend1 {
margin-bottom:-1em;
}
#legend2, #links, h1, #footer {
text-align:center;
margin-bottom:1em;
}
.engine-legend li, #links li, #footer li {
display:inline;
}
.engine-legend li {
border-left:1.2em solid #FFF;
padding-left:.5em;
margin-right:2em;
}
.engine-legend #tracing {
border-color:#FFA451;
}
.engine-legend #jaeger {
border-color:#3E99D7;
}
.engine-legend #moz-mooj {
border-color:#6f0a93;
}
.engine-legend #google-v8 {
border-color:#4DA74D;
}
.engine-legend #apple-nitro {
border-color:#CF4B4B;
}
.engine-legend #interpreter {
border-color:#737373;
}
.engine-legend #apple-jsci {
border-color:#EF8B8B;
}
.engine-legend #moz-mooi {
border-color:#027364;
}
.engine-legend #moz-moom {
border-color:#000000;
}
#links li, #footer li {
border-right:1px solid #000;
padding:0 1.265em 0 1em;
}
#links li:last-child, #footer li:last-child {
border:none;
}
#lastUpdate {
float:right;
margin-bottom:1em;
color: gray;
font-size: x-small;
}
#faq {
margin:2em auto;
width:80%;
}
#faq li {
font-weight:700
}
#faq li p:last-child {
font-weight:normal;
}

Просмотреть файл

@ -0,0 +1,295 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-language" content="en">
<meta http-equiv="refresh" content="300">
<title>ARE WE FAST YET?</title>
<link rel="stylesheet" title="Default Stylesheet" type="text/css" href="style.css">
<link rel="alternate" type="application/rss+xml" title="RSS feeds" href="rss.php">
<link rel="shortcut icon" href="http://www.arewefastyet.com/awfy_favicon.png">
<script type="text/javascript" src="flot/jquery.js"></script>
<script type="text/javascript" src="flot/jquery.flot.js"></script>
</head>
<body>
<div id="graph-container">
<div id="sunspider-label">sunspider<span id="sunspider-speed"></span></div>
<div id="v8-label">v8bench<span id="v8-speed"></span></div>
<div id="sunspider-graph"></div>
<div id="v8-graph"></div>
</div>
<ul class="engine-legend" id="legend1">
<li id="moz-mooj">mozilla firefox 4 (TM+JM)</li>
<li id="google-v8">google chrome (v8)</li>
</ul>
<ul class="engine-legend" id="legend2">
{if $MACHINE == 5 or $MACHINE == 4}
<li id="apple-nitro">apple safari (nitro)</li>
{else}
<li id="moz-moom">mozilla firefox (JM only)</li>
<li id="tracing">mozilla firefox (TM only)</li>
{/if}
</ul>
<script type="text/javascript">
{literal}
var fullNames = {
jm: 'tracemonkey',
tm: 'tracemonkey',
v8: 'v8',
jsc: 'WebKit',
jsci: 'WebKit',
moo: 'tracemonkey',
};
function calcPercentDiff(currentValue, previousValue) {
return -Math.round(((currentValue - previousValue) / previousValue) * 1000) / 10;
}
function getLowestNitroV8SetNumber(dsets) {
var nitroSetNumber = -1;
var v8SetNumber = -1;
for (var i = 0; i < dsets.length; i++) {
if (dsets[i].name == "nitro") {
nitroSetNumber = i;
} else if (dsets[i].name == "v8") {
v8SetNumber = i;
}
}
if ((nitroSetNumber > -1) && (dsets[nitroSetNumber].data[dsets[nitroSetNumber,1].data.length - 1][1] < dsets[v8SetNumber].data[dsets[v8SetNumber,1].data.length - 1][1])) {
return nitroSetNumber;
} else {
return v8SetNumber;
}
}
function getTitlePercentDiff(dsets) {
var dataLength = dsets[3].data.length -1; //ID for last Jaeger dataset
var lastJaeger = dsets[3].data[dataLength][1]; //last speed data point for Jaeger
var target = dsets[getLowestNitroV8SetNumber(dsets)].data[dataLength][1]; //set Target to the lowest last value of V8 and Nitro
var percentDiff = calcPercentDiff(lastJaeger,target); //get the percent diff between Jaeger and the Target
if (percentDiff > 10) percentDiff = Math.round(percentDiff);//if the percent diff is above 10, round to eliminate 10ths
var direction = "slower"; //set speed direction Slower/Faster from Jaeger value compared to Target
if (lastJaeger < target) direction = "FASTER!";
var titlePercent = ' is ' + percentDiff +'% ' + direction;
return titlePercent;
}
function colorForName(name) {
return ({ nitro: "#cf4b4b",
interp: "#bbbbbb",
v8: "#4da74d",
jaeger: "#6f0a93",
{/literal}
{if $MACHINE == 4 || $MACHINE == 5}
tracer: "#6f0a93",
{else}
tracer: "#ffa451",
{/if}
{literal}
jsci: "#EF8B8B",
mooi: "#027364",
moom: "#000000",
mooj: "#6f0a93",
jmnotrc: "#3e99d7"})[name];
}
function fillColorForName(name) {
return "#ffffff";
}
function drawGraph(sel, dsets) {
var sets = [];
var jaegerSetNumber = 3;
for (var i = 0; i < dsets.length; i++) {
var dataRadius = 2.0;
if (dsets[i].name == "jaeger") {
jaegerSetNumber = i;
}
sets[i] = {
lines: { show: true },
points: { show: true,
fillColor: fillColorForName(dsets[i].name),
},
borderWidth: 1.5,
borderColor: "#BEBEBE",
markingsLineWidth: .75,
hoverable: true,
clickable: true,
label: dsets[i].name,
data: dsets[i].data,
color: colorForName(dsets[i].name),
shadowSize: 0
};
}
var options = { yaxis: {
min: 0,
tickFormatter:
function (v, axis) { return v + "ms"; }
},
xaxis: {
tickFormatter:
function (v, axis) {
v = Math.round(v);
if (!(v in runTimes))
return '';
return runTimes[v].substr(0, runTimes[v].indexOf(','));
}
},
legend:
{
show: false
},
grid:
{
hoverable: true,
clickable: true
}
};
function showToolTip(x, y, contents) {
var tipWidth = 165;
var tipHeight = 75;
var xOffset = 5;
var yOffset = 5;
var ie = document.all && !window.opera;
var iebody = (document.compatMode == "CSS1Compat")
? document.documentElement
: document.body;
var scrollLeft = ie ? iebody.scrollLeft : window.pageXOffset;
var scrollTop = ie ? iebody.scrollTop : window.pageYOffset;
var docWidth = ie ? iebody.clientWidth - 15 : window.innerWidth - 15;
var docHeight = ie ? iebody.clientHeight - 15 : window.innerHeight - 18;
y = (y + tipHeight - scrollTop > docHeight)
? y - tipHeight - 5 - (yOffset * 2)
: y; // account for bottom edge
// account for right edge
if (x + tipWidth - scrollLeft > docWidth) {
$('<div id="tooltip">' + contents + '<\/div>').css( {
top: y + yOffset,
right: docWidth - x + xOffset,
}).appendTo("body").fadeIn(200);
} else {
$('<div id="tooltip">' + contents + '<\/div>').css( {
top: y + yOffset,
left: x + xOffset,
}).appendTo("body").fadeIn(200);
}
}
var previousPoint = null;
$.plot(sel, sets, options);
sel.bind("plothover", function (event, pos, item) {
if (item) {
if (!previousPoint ||
(previousPoint[0] != item.datapoint[0]) ||
(previousPoint[1] != item.datapoint[1])) {
previousPoint = item.datapoint;
$("#tooltip").remove();
var x = item.datapoint[0];
var y = item.datapoint[1];
var e = engineNames[item.seriesIndex];
var text = 'speed: ' + y + "ms" + "<br>";
if (x > 0) {
var thisValue = parseFloat(y);
var prevValue = parseFloat(item.series.data[x-1,x-1][1]);
var speedDiff = Math.round((thisValue - prevValue)*10)/10;
var pdiff = calcPercentDiff(thisValue, prevValue);
var fbofw;
if (pdiff < 0) {
fbofw = "worse";
pdiff = -pdiff;
} else {
fbofw = "better";
}
if (speedDiff === speedDiff) {
text += String.fromCharCode(916) + ": " + speedDiff + 'ms (' +
pdiff + "% " + fbofw + ")<br>";
}
}
var fullName = fullNames[e];
text += "source: " + fullName + "<br>";
text += "rev: ";
var cset = engineBuilds[e][x];
if (cset) {
if (fullName == "tracemonkey") {
text += "<a href=\"http://hg.mozilla.org/tracemonkey/rev/" + cset +
"\">" + cset + "</a>";
} else if (fullName == "v8") {
text += "<a href=\"http://code.google.com/p/v8/source/detail?r=" + cset +
"\">" + cset + "</a>";
} else if (fullName == "WebKit") {
text += "<a href=\"http://trac.webkit.org/changeset/" + cset +
"\">" + cset + "</a>";
} else {
text += cset;
}
} else {
text += 'unknown';
}
text += "<br>";
var buildTime = runTimes[x];
text += "tested: " + buildTime;
showToolTip(item.pageX, item.pageY, text);
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
}
var runTimes = [
{/literal}
{foreach from=$runTimes item=v name=runtimes}
'{$v}'{if !$smarty.foreach.runtimes.last},{/if}
{/foreach}
{literal}
];
var engineBuilds = {
{/literal}
{foreach from=$engineBuilds key=k item=v name=emap}
{$k}: [ {$v} ]{if !$smarty.foreach.emap.last},{/if}
{/foreach}
{literal}
};
var engineNames = {/literal}{$engineMapping}{literal};
function drawSelfSS() {
var dsets = [
{/literal}
{foreach from=$self_ss item=set}
{literal}{{/literal}
name: "{$set.name}",
data: {$set.data}
{literal}}{/literal},
{/foreach}
{literal}
];
drawGraph($("#sunspider-graph"), dsets);
//document.getElementById('sunspider-speed').innerHTML = getTitlePercentDiff(dsets);
}
function drawSelfV8() {
var dsets = [
{/literal}
{foreach from=$self_v8 item=set}
{literal}{{/literal}
name: "{$set.name}",
data: {$set.data}
{literal}}{/literal},
{/foreach}
{literal}
];
drawGraph($("#v8-graph"), dsets);
//document.getElementById('v8-speed').innerHTML = getTitlePercentDiff(dsets);
}
$(document).ready(function () {
drawSelfSS();
drawSelfV8();
});
{/literal}
</script>
<ul id="links">
<li><a href="?machine=5">x86</a></li>
<li><a href="?machine=4">x64</a></li>
<!-- <li><a href="?machine=3">ARM</a></li> -->
<li><a href="?machine=6">regress-x86</a></li>
<li><a href="?machine=7">regress-x64</a></li>
<li><a href="faq.html">FAQ</a></li>
<li><a href="awfy2.php?machine=9">beta awfy2</a></li>
<li><a href="mailto:danderson@mozilla.com">suggestions</a></li>
</ul>
</body>
</html>

Просмотреть файл

@ -0,0 +1,251 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-language" content="en">
<title>ARE WE FAST YET?</title>
<link rel="stylesheet" title="Default Stylesheet" type="text/css" href="style-indiv.css">
<link rel="alternate" type="application/rss+xml" title="RSS feeds" href="rss.php">
<link rel="shortcut icon" href="http://www.arewefastyet.com/awfy_favicon.png">
<script type="text/javascript" src="MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="flot/jquery.js"></script>
<script type="text/javascript" src="flot/jquery.flot.js"></script>
</head>
<body>
<ul class="engine-legend" id="legend1">
<li id="tracing">moz tracing JIT</li>
{if $MACHINE >= 6}
<li id="jaeger-and-tracing">moz method+tracing</li>
{else}
<li id="google-v8">google v8</li>
{if $MACHINE != 3}
<li id="apple-nitro">apple nitro</li>
{/if}
{/if}
</ul>
{if $MACHINE >= 4}
<ul class="engine-legend" id="legend2">
<li id="moz-moom">moz method JIT</li>
{if $MACHINE >= 6}
<li id="google-v8">google v8</li>
{/if}
</ul>
{/if}
{foreach from=$tests item=test}
<div class="graph-label">{$test.name}</div>
<div class="graph" id="graph-{$test.name}"></div>
<p>&nbsp;</p>
{/foreach}
<script type="text/javascript">
{literal}
var fullNames = {
jm: 'jaegermonkey',
tm: 'tracemonkey',
v8: 'v8',
jsc: 'WebKit',
jsci: 'WebKit',
moo: 'jm-fatvals'
};
function calcPercentDiff(currentValue, previousValue) {
return -Math.round(((currentValue - previousValue) / previousValue) * 1000) / 10;
}
function getLowestNitroV8SetNumber(dsets) {
var nitroSetNumber = -1;
var v8SetNumber = -1;
for (var i = 0; i < dsets.length; i++) {
if (dsets[i].name == "nitro") {
nitroSetNumber = i;
} else if (dsets[i].name == "v8") {
v8SetNumber = i;
}
}
if ((nitroSetNumber > -1) && (dsets[nitroSetNumber].data[dsets[nitroSetNumber,1].data.length - 1][1] < dsets[v8SetNumber].data[dsets[v8SetNumber,1].data.length - 1][1])) {
return nitroSetNumber;
} else {
return v8SetNumber;
}
}
function getTitlePercentDiff(dsets) {
var dataLength = dsets[3].data.length -1; //ID for last Jaeger dataset
var lastJaeger = dsets[3].data[dataLength][1]; //last speed data point for Jaeger
var target = dsets[getLowestNitroV8SetNumber(dsets)].data[dataLength][1]; //set Target to the lowest last value of V8 and Nitro
var percentDiff = calcPercentDiff(lastJaeger,target); //get the percent diff between Jaeger and the Target
if (percentDiff > 10) percentDiff = Math.round(percentDiff);//if the percent diff is above 10, round to eliminate 10ths
var direction = "slower"; //set speed direction Slower/Faster from Jaeger value compared to Target
if (lastJaeger < target) direction = "FASTER!";
var titlePercent = ' is ' + percentDiff +'% ' + direction;
return titlePercent;
}
function colorForName(name) {
return ({ nitro: "#cf4b4b",
interp: "#bbbbbb",
v8: "#4da74d",
jaeger: "#6f0a93",
tracer: "#ffa451",
jsci: "#EF8B8B",
mooi: "#027364",
mooj: "#6f0a93",
moom: "#000000",
jmnotrc: "#3e99d7"})[name];
}
function fillColorForName(name) {
return "#ffffff";
}
function drawGraph(sel, dsets) {
var sets = [];
var jaegerSetNumber = 3;
for (var i = 0; i < dsets.length; i++) {
var dataRadius = 1.8;
if (dsets[i].name == "jaeger") {
jaegerSetNumber = i;
}
sets[i] = {
lines: { show: true },
points: { show: true,
fillColor: fillColorForName(dsets[i].name),
radius: dataRadius
},
borderWidth: 1.5,
borderColor: "#BEBEBE",
markingsLineWidth: .75,
hoverable: true,
clickable: true,
label: dsets[i].name,
data: dsets[i].data,
color: colorForName(dsets[i].name),
shadowSize: 0
};
}
var options = { yaxis: {
min: 0,
tickFormatter:
function (v, axis) { return v + "ms"; }
},
xaxis: {
tickFormatter:
function (v, axis) {
v = Math.round(v);
if (!(v in runTimes))
return '';
return runTimes[v].substr(0, runTimes[v].indexOf(','));
}
},
legend: {
show: false
},
grid: {
hoverable: true,
clickable: true
}
};
function showToolTip(x, y, contents) {
$('<div id="tooltip">' + contents + '<\/div>').css( {
top: y + 5,
left: x + 5,
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$.plot(sel, sets, options);
sel.bind("plothover", function (event, pos, item) {
if (item) {
if (!previousPoint ||
(previousPoint[0] != item.datapoint[0]) ||
(previousPoint[1] != item.datapoint[1])) {
previousPoint = item.datapoint;
$("#tooltip").remove();
var x = item.datapoint[0];
var y = item.datapoint[1];
var e = engineNames[item.seriesIndex];
var text = 'speed: ' + y + "ms" + "<br>";
if (x > 0) {
var thisValue = parseFloat(y);
var prevValue = parseFloat(item.series.data[x-1,x-1][1]);
var speedDiff = Math.round((thisValue - prevValue)*10)/10;
var pdiff = calcPercentDiff(thisValue, prevValue);
var fbofw;
if (pdiff < 0) {
fbofw = "worse";
pdiff = -pdiff;
} else {
fbofw = "better";
}
text += String.fromCharCode(916) + ": " + speedDiff + 'ms (' +
pdiff + "% " + fbofw + ")<br>";
}
var fullName = fullNames[e];
text += "source: " + fullName + "<br>";
text += "rev: ";
var cset = engineBuilds[e][x];
if (cset) {
if (fullName == "tracemonkey") {
text += "<a href=\"http://hg.mozilla.org/tracemonkey/rev/" + cset +
"\">" + cset + "</a>";
} else if (fullName == "v8") {
text += "<a href=\"http://code.google.com/p/v8/source/detail?r=" + cset +
"\">" + cset + "</a>";
} else if (fullName == "WebKit") {
text += "<a href=\"http://trac.webkit.org/changeset/" + cset +
"\">" + cset + "</a>";
} else {
text += cset;
}
} else {
text += 'unknown';
}
text += "<br>";
var buildTime = runTimes[x];
text += "tested: " + buildTime;
showToolTip(item.pageX, item.pageY, text);
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
}
var runTimes = [
{/literal}
{foreach from=$runTimes item=v name=runtimes}
'{$v}'{if !$smarty.foreach.runtimes.last},{/if}
{/foreach}
{literal}
];
var engineBuilds = {
{/literal}
{foreach from=$engineBuilds key=k item=v name=emap}
{$k}: [ {$v} ]{if !$smarty.foreach.emap.last},{/if}
{/foreach}
{literal}
};
var engineNames = {/literal}{ $engineMapping }{literal};
function drawAllGraphs() {
var dsets;
{/literal}
{foreach from=$tests item=test}
dsets = [
{foreach from=$test.lines item=line}
{literal}{{/literal}
name: "{$line.name}",
data: {$line.data}
{literal}}{/literal},
{/foreach}
];
drawGraph($("#graph-{$test.name}"), dsets);
{/foreach}
{literal}
}
MochiKit.DOM.addLoadEvent(drawAllGraphs);
{/literal}
</script>
<ul id="links">
<li><a href="?machine=5">x86 graphs</a></li>
<li><a href="?machine=4">x64 graphs</a></li>
<li><a href="?machine=3">ARM graphs</a></li>
<li><a href="faq.html">FAQ</a></li>
<li><a href="mailto:danderson@mozilla.com">suggestions</a></li>
</ul>
</body>
</html>

Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Are We Fast Yet?</title>
<link>http://www.arewefastyet.com/</link>
<description>Tracks JavaScript performance</description>
<language>en-us</language>
<pubDate>{$runs[0].date}</pubDate>
<lastBuildDate>{$runs[0].date}</lastBuildDate>
{foreach from=$runs item=run}
<item>
<title>{$run.cpu}-{$run.os} cset {$run.cset}</title>
<link>http://www.arewefastyet.com/?machine={$run.machine}</link>
<pubDate>{$run.date}</pubDate>
</item>
{/foreach}
</channel>
</rss>

59
website/UPDATE.php Normal file
Просмотреть файл

@ -0,0 +1,59 @@
<?php
require_once("internals.php");
init_database();
if (isset($_GET['run']) && $_GET['run'] == 'yes') {
$CPU = mysql_real_escape_string(GET_string('CPU'));
$OS = mysql_real_escape_string(GET_string('OS'));
$MACHINE = GET_int('MACHINE');
$CSET = mysql_real_escape_string(GET_string('CSET'));
mysql_query("INSERT INTO fast_run (cpu, os, machine, stamp, cset)
VALUES
('$CPU', '$OS', $MACHINE, UNIX_TIMESTAMP(), '$CSET')")
or die("ERROR: " . mysql_error());
print("id=" . mysql_insert_id());
} else if (isset($_GET['run']) && $_GET['run'] == 'finish') {
$runid = GET_int('runid');
$status = GET_int('status');
if (isset($_GET['error']))
$error = '\'' . mysql_real_escape_string(GET_string('error')) . '\'';
else
$error = 'NULL';
mysql_query("UPDATE fast_run
SET status = $status,
error = $error
WHERE id = $runid")
or die("ERROR: " . mysql_error());
} else if (isset($_GET['run']) && $_GET['run'] == 'addEngine') {
$runid = GET_int('runid');
$mode_id = find_mode(GET_string('name'));
$cset = mysql_real_escape_string(GET_string('cset'));
mysql_query("INSERT INTO awfy_build
(run_id, mode_id, cset)
VALUES
($runid, $mode_id, '$cset')")
or die("ERROR: " . mysql_error());
} else {
$name = mysql_real_escape_string(GET_string('name'));
$time = mysql_real_escape_string(GET_string('time'));
$suite_id = find_suite(GET_string('suite'));
$mode_id = find_mode(GET_string('mode'));
$run = GET_int('run');
if ($name == '__total__') {
mysql_query("INSERT INTO awfy_score
(run_id, suite_id, mode_id, score)
VALUES
($run, $suite_id, $mode_id, $time)")
or die("ERROR: " . mysql_error());
} else {
mysql_query("INSERT INTO awfy_breakdown
(run_id, suite_id, mode_id, test, score)
VALUES
($run, $suite_id, $mode_id, '$name', $time)")
or die("ERROR: " . mysql_error());
}
}
?>

Двоичные данные
website/awfy_favicon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

228
website/context.php Normal file
Просмотреть файл

@ -0,0 +1,228 @@
<?php
// vim: set ts=4 sw=4 tw=99 et:
class Context
{
var $vendors;
var $vendorMap_;
var $modes;
var $modeMap_;
var $machine_id;
var $run_count;
var $view;
var $vars;
function Context() {
$this->vendors = array();
$this->vendorMap_ = array();
// Create an array of vendors, and a reverse mapping from DB ids.
$query = "SELECT id, name, vendor, csetURL, browser FROM awfy_vendor";
$result = awfy_query($query);
while (($row = mysql_fetch_assoc($result)) !== FALSE) {
$this->vendorMap_[$row['id']] = count($this->vendors);
$this->vendors[] = $row;
}
// Create an array of modes, and a reverse mapping from DB ids.
$query = "SELECT id, vendor_id, mode, name, color FROM awfy_mode";
$result = awfy_query($query);
while (($row = mysql_fetch_assoc($result)) !== FALSE) {
$this->modeMap_[$row['id']] = count($this->modes);
$row['vendor'] = $this->vendorMap_[$row['vendor_id']];
$row['used'] = false;
$this->modes[] = $row;
}
$this->vars = array();
$this->machine_id = 9;
if (isset($_GET['machine'])) {
$this->machine_id = intval($_GET['machine']);
$this->vars['machine'] = $this->machine_id;
}
$this->run_count = 32;
if (isset($_GET['runs'])) {
if (intval($_GET['runs']) > 1) {
$this->run_count = intval($_GET['runs']);
$this->vars['runs'] = $this->run_count;
}
}
$this->view = 'overall';
if (isset($_GET['view'])) {
$view = $_GET['view'];
if ($view == 'breakdown' || $view == 'regress') {
$this->view = $view;
$this->vars['view'] = $this->view;
}
}
}
function markModeUsed($mode_id) {
$mode = $this->modeFromDB($mode_id);
$this->modes[$mode]['used'] = true;
}
function url($new_vars) {
$r = $this->vars;
foreach ($new_vars as $key => $value) {
if (!$value)
unset($r[$key]);
else
$r[$key] = $value;
}
$query = http_build_query($r);
if ($query == "")
return "?a=b";
return '?' . $query;
}
function modeFromDB($mode_id) {
return $this->modeMap_[$mode_id];
}
}
class RunFilter
{
var $machine_id;
var $run_count;
var $suite_id;
var $runs;
var $runmap;
var $idstr;
var $modemap;
var $series;
var $level;
function RunFilter($cx, $machine_id, $run_count, $suite_id) {
$this->machine_id = $machine_id;
$this->run_count = $run_count;
$this->suite_id = $suite_id;
$this->runs = $this->findRuns();
$this->level = ($cx->view == 'overall') ? 1 : 10;
// Get the list of run IDs for this graph.
$ids = array();
$this->runmap = array();
for ($i = 0; $i < count($this->runs); $i++) {
$ids[] = $this->runs[$i]['id'];
$this->runmap[$this->runs[$i]['id']] = $i;
}
$this->idstr = implode(',', $ids);
if (count($ids) == 0)
die("unknown machine ID");
// Find the list of modes that apply to this filter. Note that the
// driver guarantees filling awfy_score only iff awfy_breakdown was
// filled correctly, so it suffices to only check awfy_score even if
// the filter includes a particular test case.
$query = "SELECT s.mode_id
FROM awfy_score s
JOIN awfy_mode m ON s.mode_id = m.id
WHERE s.run_id IN (" . $this->idstr . ")
AND m.level <= " . $this->level . "
AND s.suite_id = " . $this->suite_id . "
GROUP BY s.mode_id";
$result = awfy_query($query);
$this->modemap = array();
$this->series = array();
while (($row = mysql_fetch_assoc($result)) !== FALSE) {
$mode_id = $row['mode_id'];
$this->modemap[$mode_id] = count($this->series);
$this->series[] = array('mode' => $cx->modeFromDB($mode_id));
$cx->markModeUsed($mode_id);
}
// To each series, add a vector that maps run indexes to changeset
// information about that series.
$query = "SELECT ab.run_id, ab.mode_id, ab.cset
FROM awfy_build ab
JOIN awfy_mode m ON ab.mode_id = m.id
WHERE ab.run_id IN (" . $this->idstr . ")
AND m.level <= " . $this->level;
$result = awfy_query($query);
while (($row = mysql_fetch_assoc($result)) !== FALSE) {
$mode_id = $row['mode_id'];
$run_id = $row['run_id'];
$mode = $this->findSeriesOfMode($mode_id);
$run = $this->findRun($run_id);
if (!isset($this->modemap[$mode_id]))
continue;
$this->series[$mode]['csets'][$run] = $row['cset'];
}
}
function findSeriesOfMode($mode_id) {
return $this->modemap[$mode_id];
}
function findRuns() {
$query = "SELECT fr.id, fr.stamp
FROM fast_run fr
JOIN awfy_score a
ON fr.id = a.run_id
WHERE fr.machine = " . $this->machine_id . "
AND fr.status <> 0
GROUP BY fr.id
ORDER BY fr.stamp DESC
LIMIT " . $this->run_count;
$result = awfy_query($query);
$rows = array();
while (($row = mysql_fetch_assoc($result)) !== FALSE)
$rows[] = $row;
return array_reverse($rows);
}
function findRun($run_id) {
return $this->runmap[$run_id];
}
function FromGET($cx, $suite_id) {
$machine_id = $cx->machine_id;
$run_count = $cx->run_count;
return new RunFilter($cx, $machine_id, $run_count, $suite_id);
}
}
class GraphBuilder
{
var $idstr;
var $series;
var $runs;
function GraphBuilder(&$cx, &$filter, $test_name = FALSE) {
$this->runs = $filter->runs;
// PHP arrays are by value, so this is safe.
$this->series = $filter->series;
// Finally, get statistics for this graph.
if (!$test_name) {
$query = "SELECT s.run_id, s.mode_id, s.score
FROM awfy_score s
JOIN awfy_mode m ON m.id = s.mode_id
WHERE s.suite_id = " . $filter->suite_id . "
AND m.level <= " . $filter->level . "
AND s.run_id IN (" . $filter->idstr . ")";
} else {
$query = "SELECT b.run_id, b.mode_id, b.score
FROM awfy_breakdown b
WHERE b.suite_id = " . $filter->suite_id . "
AND b.run_id IN (" . $filter->idstr . ")
AND b.test = '" . mysql_real_escape_string($test_name) . "'";
}
$result = awfy_query($query);
while (($row = mysql_fetch_assoc($result)) !== FALSE) {
$run_id = $row['run_id'];
$mode_id = $row['mode_id'];
$mode = $filter->findSeriesOfMode($mode_id);
$run = $filter->findRun($run_id);
$this->series[$mode]['scores'][$run] = $row['score'];
}
}
}
?>

62
website/faq.html Normal file
Просмотреть файл

@ -0,0 +1,62 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AWFY - Frequently Asked Questions</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h1>Frequently Asked Questions</h1>
<ol id="faq">
<li>
<p>What's this site?</p>
<p>This site tracks the performance of popular JavaScript engines.</p>
</li>
<li>
<p>What versions are you testing with?</p>
<p>Each test run checks out a copy of the latest source code for each vendor it's testing. This means we're testing the latest, greatest, unstable, bleeding-edge versions of browsers' JS engines. The scores here may not represent what you see in stable releases.</p>
</li>
<li>
<p>Who's behind it? Is Mozilla?</p>
<p>This site is maintained by Mozilla's JavaScript team.</p>
Special thanks to wx24 for the new layout, and Michael Clackler for the UI improvements such as hover-tip deltas. Awesome!
</li>
<li>
<p>Why does the v8 benchmark go down, instead of up?</p>
<p>The v8 benchmark produces a score, not raw time. We inverted the graph so they all look like "lower is better".</p>
</li>
<li>
<p>Why do some changesets appear multiple times?</p>
<p>The graphs update on every v8 or tracemonkey check-in, roughly, so if one updates but not the other, the same changeset can be tested twice.</p>
</li>
<li>
<p>Why isn't Opera/IE/something here?</p>
<p>Right now, the performance tests are run on a Mac, which means no IE. Also the tests rely on a "shell" JS engine that runs in a command line. It doesn't test browsers. We'll change that, eventually.</p>
</li>
<li>
<p>What are the axes?</p>
<p>The Y axis is time to benchmark completion. Lower is better. The X axis represents test runs, chronologically. The left-most run is the oldest, the right-most run is the latest.</p>
</li>
<li>
<p>What are the graphs?</p>
<p>The top left-hand graph is Mozilla's Kraken benchmark. The top right-hand graph is Apple's SunSpider benchmark. The bottom graph is Google's V8 benchmark suite.</p>
</li>
<li>
<p>What do the hover tips mean?</p>
<p>"Time" is...time. "Source" is where we got the engine from. "Tested" is when we downloaded the engine, compiled, and tested it. "Rev" is the unique point in the engine's revision history we tested. These numbers/strings are for developers to see which changes happened in between points in the graph.</p>
</li>
<li>
<p>What runs the tests?</p>
<p>A mac-mini.</p>
</li>
<li>
<p>What's ARM?</p>
<p>ARM is the CPU present in many embedded devices, like smartphones. We're interested in this for mobile Firefox.</p>
</li>
<li>
<p>Is this open source?</p>
<p>It's not very interesting (or good), but yes: <a href="http://hg.mozilla.org/users/danderson_mozilla.com/awfy">click here</a></p>
</li>
</ol>
</body>
</html>

1024
website/flot/API.txt Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

71
website/flot/FAQ.txt Normal file
Просмотреть файл

@ -0,0 +1,71 @@
Frequently asked questions
--------------------------
Q: How much data can Flot cope with?
A: Flot will happily draw everything you send to it so the answer
depends on the browser. The excanvas emulation used for IE (built with
VML) makes IE by far the slowest browser so be sure to test with that
if IE users are in your target group.
1000 points is not a problem, but as soon as you start having more
points than the pixel width, you should probably start thinking about
downsampling/aggregation as this is near the resolution limit of the
chart anyway. If you downsample server-side, you also save bandwidth.
Q: Flot isn't working when I'm using JSON data as source!
A: Actually, Flot loves JSON data, you just got the format wrong.
Double check that you're not inputting strings instead of numbers,
like [["0", "-2.13"], ["5", "4.3"]]. This is most common mistake, and
the error might not show up immediately because Javascript can do some
conversion automatically.
Q: Can I export the graph?
A: This is a limitation of the canvas technology. There's a hook in
the canvas object for getting an image out, but you won't get the tick
labels. And it's not likely to be supported by IE. At this point, your
best bet is probably taking a screenshot, e.g. with PrtScn.
Q: The bars are all tiny in time mode?
A: It's not really possible to determine the bar width automatically.
So you have to set the width with the barWidth option which is NOT in
pixels, but in the units of the x axis (or the y axis for horizontal
bars). For time mode that's milliseconds so the default value of 1
makes the bars 1 millisecond wide.
Q: Can I use Flot with libraries like Mootools or Prototype?
A: Yes, Flot supports it out of the box and it's easy! Just use jQuery
instead of $, e.g. call jQuery.plot instead of $.plot and use
jQuery(something) instead of $(something). As a convenience, you can
put in a DOM element for the graph placeholder where the examples and
the API documentation are using jQuery objects.
Depending on how you include jQuery, you may have to add one line of
code to prevent jQuery from overwriting functions from the other
libraries, see the documentation in jQuery ("Using jQuery with other
libraries") for details.
Q: Flot doesn't work with [widget framework xyz]!
A: The problem is most likely within the framework, or your use of the
framework.
The only non-standard thing used by Flot is the canvas tag; otherwise
it is simply a series of absolute positioned divs within the
placeholder tag you put in. If this is not working, it's probably
because the framework you're using is doing something weird with the
DOM. As a last resort, you might try replotting and see if it helps.
If you find there's a specific thing we can do to Flot to help, feel
free to submit a bug report. Otherwise, you're welcome to ask for help
on the mailing list, but please don't submit a bug report to Flot -
try the framework instead.

22
website/flot/LICENSE.txt Normal file
Просмотреть файл

@ -0,0 +1,22 @@
Copyright (c) 2007-2009 IOLA and Ole Laursen
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

15
website/flot/Makefile Normal file
Просмотреть файл

@ -0,0 +1,15 @@
# Makefile for generating minified files
YUICOMPRESSOR_PATH=../yuicompressor-2.3.5.jar
# if you need another compressor path, just copy the above line to a
# file called Makefile.local, customize it and you're good to go
-include Makefile.local
.PHONY: all
# we cheat and process all .js files instead of listing them
all: $(patsubst %.js,%.min.js,$(filter-out %.min.js,$(wildcard *.js)))
%.min.js: %.js
java -jar $(YUICOMPRESSOR_PATH) $< -o $@

340
website/flot/NEWS.txt Normal file
Просмотреть файл

@ -0,0 +1,340 @@
Flot 0.6
--------
API changes:
1. Selection support has been moved to a plugin. Thus if you're
passing selection: { mode: something }, you MUST include the file
jquery.flot.selection.js after jquery.flot.js. This reduces the size
of base Flot and makes it easier to customize the selection as well as
improving code clarity. The change is based on patch from andershol.
2. In the global options specified in the $.plot command,
"lines", "points", "bars" and "shadowSize" have been moved to a
sub-object called "series", i.e.
$.plot(placeholder, data, { lines: { show: true }})
should be changed to
$.plot(placeholder, data, { series: { lines: { show: true }}})
All future series-specific options will go into this sub-object to
simplify plugin writing. Backward-compatibility code is in place, so
old code should not break.
3. "plothover" no longer provides the original data point, but instead
a normalized one, since there may be no corresponding original point.
4. Due to a bug in previous versions of jQuery, you now need at least
jQuery 1.2.6. But if you can, try jQuery 1.3.2 as it got some
improvements in event handling speed.
Changes:
- Added support for disabling interactivity for specific data series
(request from Ronald Schouten and Steve Upton).
- Flot now calls $() on the placeholder and optional legend container
passed in so you can specify DOM elements or CSS expressions to make
it easier to use Flot with libraries like Prototype or Mootools or
through raw JSON from Ajax responses.
- A new "plotselecting" event is now emitted while the user is making
a selection.
- The "plothover" event is now emitted immediately instead of at most
10 times per second, you'll have to put in a setTimeout yourself if
you're doing something really expensive on this event.
- The built-in date formatter can now be accessed as
$.plot.formatDate(...) (suggestion by Matt Manela) and even
replaced.
- Added "borderColor" option to the grid (patch from Amaury Chamayou
and patch from Mike R. Williamson).
- Added support for gradient backgrounds for the grid, take a look at
the "setting options" example (based on patch from Amaury Chamayou,
issue 90).
- Gradient bars (suggestion by stefpet).
- Added a "plotunselected" event which is triggered when the selection
is removed, see "selection" example (suggestion by Meda Ugo);
- The option legend.margin can now specify horizontal and vertical
margins independently (suggestion by someone who's annoyed).
- Data passed into Flot is now copied to a new canonical format to
enable further processing before it hits the drawing routines. As a
side-effect, this should make Flot more robust in the face of bad
data (and fixes issue 112).
- Step-wise charting: line charts have a new option "steps" that when
set to true connects the points with horizontal/vertical steps
instead of diagonal lines.
- The legend labelFormatter now passes the series in addition to just
the label (suggestion by Vincent Lemeltier).
- Horizontal bars (based on patch by Jason LeBrun).
- Support for partial bars by specifying a third coordinate, i.e. they
don't have to start from the axis. This can be used to make stacked
bars.
- New option to disable the (grid.show).
- Added pointOffset method for converting a point in data space to an
offset within the placeholder.
- Plugin system: register an init method in the $.flot.plugins array
to get started, see PLUGINS.txt for details on how to write plugins
(it's easy). There are also some extra methods to enable access to
internal state.
- Hooks: you can register functions that are called while Flot is
crunching the data and doing the plot. This can be used to modify
Flot without changing the source, useful for writing plugins. Some
hooks are defined, more are likely to come.
- Threshold plugin: you can set a threshold and a color, and the data
points below that threshold will then get the color. Useful for
marking data below 0, for instance.
- Stack plugin: you can specify a stack key for each series to have
them summed. This is useful for drawing additive/cumulative graphs
with bars and (currently unfilled) lines.
- Crosshairs plugin: trace the mouse position on the axes, enable with
crosshair: { mode: "x"} (see the new tracking example for a use).
- Image plugin: plot prerendered images.
- Navigation plugin for panning and zooming a plot.
- More configurable grid.
- Axis transformation support, useful for non-linear plots, e.g. log
axes and compressed time axes (like omitting weekends).
- Support for twelve-hour date formatting (patch by Forrest Aldridge).
- The color parsing code in Flot has been cleaned up and split out so
it's now available as a separate jQuery plugin. It's included inline
in the Flot source to make dependency managing easier. This also
makes it really easy to use the color helpers in Flot plugins.
Bug fixes:
- Fixed two corner-case bugs when drawing filled curves (report and
analysis by Joshua Varner).
- Fix auto-adjustment code when setting min to 0 for an axis where the
dataset is completely flat on that axis (report by chovy).
- Fixed a bug with passing in data from getData to setData when the
secondary axes are used (issue 65, reported by nperelman).
- Fixed so that it is possible to turn lines off when no other chart
type is shown (based on problem reported by Glenn Vanderburg), and
fixed so that setting lineWidth to 0 also hides the shadow (based on
problem reported by Sergio Nunes).
- Updated mousemove position expression to the latest from jQuery (bug
reported by meyuchas).
- Use CSS borders instead of background in legend (fix printing issue 25
and 45).
- Explicitly convert axis min/max to numbers.
- Fixed a bug with drawing marking lines with different colors
(reported by Khurram).
- Fixed a bug with returning y2 values in the selection event (fix
by exists, issue 75).
- Only set position relative on placeholder if it hasn't already a
position different from static (reported by kyberneticist, issue 95).
- Don't round markings to prevent sub-pixel problems (reported by Dan
Lipsitt).
- Make the grid border act similarly to a regular CSS border, i.e.
prevent it from overlapping the plot itself. This also fixes a
problem with anti-aliasing when the width is 1 pixel (reported by
Anthony Ettinger).
- Imported version 3 of excanvas and fixed two issues with the newer
version. Hopefully, this will make Flot work with IE8 (nudge by
Fabien Menager, further analysis by Booink, issue 133).
- Changed the shadow code for lines to hopefully look a bit better
with vertical lines.
- Round tick positions to avoid possible problems with fractions
(suggestion by Fred, issue 130).
- Made the heuristic for determining how many ticks to aim for a bit
smarter.
- Fix for uneven axis margins (report and patch by Paul Kienzle) and
snapping to ticks (concurrent report and patch by lifthrasiir).
- Fixed bug with slicing in findNearbyItems (patch by zollman).
- Make heuristic for x axis label widths more dynamic (patch by
rickinhethuis).
- Make sure points on top take precedence when finding nearby points
when hovering (reported by didroe, issue 224).
Flot 0.5
--------
Backwards API change summary: Timestamps are now in UTC. Also
"selected" event -> becomes "plotselected" with new data, the
parameters for setSelection are now different (but backwards
compatibility hooks are in place), coloredAreas becomes markings with
a new interface (but backwards compatibility hooks are in place).
Interactivity: added a new "plothover" event and this and the
"plotclick" event now returns the closest data item (based on patch by
/david, patch by Mark Byers for bar support). See the revamped
"interacting with the data" example for some hints on what you can do.
Highlighting: you can now highlight points and datapoints are
autohighlighted when you hover over them (if hovering is turned on).
Support for dual axis has been added (based on patch by someone who's
annoyed and /david). For each data series you can specify which axes
it belongs to, and there are two more axes, x2axis and y2axis, to
customize. This affects the "selected" event which has been renamed to
"plotselected" and spews out { xaxis: { from: -10, to: 20 } ... },
setSelection in which the parameters are on a new form (backwards
compatible hooks are in place so old code shouldn't break) and
markings (formerly coloredAreas).
Timestamps in time mode are now displayed according to
UTC instead of the time zone of the visitor. This affects the way the
timestamps should be input; you'll probably have to offset the
timestamps according to your local time zone. It also affects any
custom date handling code (which basically now should use the
equivalent UTC date mehods, e.g. .setUTCMonth() instead of
.setMonth().
Added support for specifying the size of tick labels (axis.labelWidth,
axis.labelHeight). Useful for specifying a max label size to keep
multiple plots aligned.
Markings, previously coloredAreas, are now specified as ranges on the
axes, like { xaxis: { from: 0, to: 10 }}. Furthermore with markings
you can now draw horizontal/vertical lines by setting from and to to
the same coordinate (idea from line support patch by by Ryan Funduk).
The "fill" option can now be a number that specifies the opacity of
the fill.
You can now specify a coordinate as null (like [2, null]) and Flot
will take the other coordinate into account when scaling the axes
(based on patch by joebno).
New option for bars "align". Set it to "center" to center the bars on
the value they represent.
setSelection now takes a second parameter which you can use to prevent
the method from firing the "plotselected" handler.
Using the "container" option in legend now overwrites the container
element instead of just appending to it (fixes infinite legend bug,
reported by several people, fix by Brad Dewey).
Fixed a bug in calculating spacing around the plot (reported by
timothytoe). Fixed a bug in finding max values for all-negative data
sets. Prevent the possibility of eternal looping in tick calculations.
Fixed a bug when borderWidth is set to 0 (reported by
Rob/sanchothefat). Fixed a bug with drawing bars extending below 0
(reported by James Hewitt, patch by Ryan Funduk). Fixed a
bug with line widths of bars (reported by MikeM). Fixed a bug with
'nw' and 'sw' legend positions. Improved the handling of axis
auto-scaling with bars. Fixed a bug with multi-line x-axis tick
labels (reported by Luca Ciano). IE-fix help by Savage Zhang.
Flot 0.4
--------
API changes: deprecated axis.noTicks in favor of just specifying the
number as axis.ticks. So "xaxis: { noTicks: 10 }" becomes
"xaxis: { ticks: 10 }"
Time series support. Specify axis.mode: "time", put in Javascript
timestamps as data, and Flot will automatically spit out sensible
ticks. Take a look at the two new examples. The format can be
customized with axis.timeformat and axis.monthNames, or if that fails
with axis.tickFormatter.
Support for colored background areas via grid.coloredAreas. Specify an
array of { x1, y1, x2, y2 } objects or a function that returns these
given { xmin, xmax, ymin, ymax }.
More members on the plot object (report by Chris Davies and others).
"getData" for inspecting the assigned settings on data series (e.g.
color) and "setData", "setupGrid" and "draw" for updating the contents
without a total replot.
The default number of ticks to aim for is now dependent on the size of
the plot in pixels. Support for customizing tick interval sizes
directly with axis.minTickSize and axis.tickSize.
Cleaned up the automatic axis scaling algorithm and fixed how it
interacts with ticks. Also fixed a couple of tick-related corner case
bugs (one reported by mainstreetmark, another reported by timothytoe).
The option axis.tickFormatter now takes a function with two
parameters, the second parameter is an optional object with
information about the axis. It has min, max, tickDecimals, tickSize.
Added support for segmented lines (based on patch from Michael
MacDonald) and for ignoring null and bad values (suggestion from Nick
Konidaris and joshwaihi).
Added support for changing the border width (joebno and safoo).
Label colors can be changed via CSS by selecting the tickLabel class.
Fixed a bug in handling single-item bar series (reported by Emil
Filipov). Fixed erratic behaviour when interacting with the plot
with IE 7 (reported by Lau Bech Lauritzen). Prevent IE/Safari text
selection when selecting stuff on the canvas.
Flot 0.3
--------
This is mostly a quick-fix release because jquery.js wasn't included
in the previous zip/tarball.
Support clicking on the plot. Turn it on with grid: { clickable: true },
then you get a "plotclick" event on the graph placeholder with the
position in units of the plot.
Fixed a bug in dealing with data where min = max, thanks to Michael
Messinides.
Include jquery.js in the zip/tarball.
Flot 0.2
--------
Added support for putting a background behind the default legend. The
default is the partly transparent background color. Added
backgroundColor and backgroundOpacity to the legend options to control
this.
The ticks options can now be a callback function that takes one
parameter, an object with the attributes min and max. The function
should return a ticks array.
Added labelFormatter option in legend, useful for turning the legend
labels into links.
Fixed a couple of bugs.
The API should now be fully documented.
Patch from Guy Fraser to make parts of the code smaller.
API changes: Moved labelMargin option to grid from x/yaxis.
Flot 0.1
--------
First public release.

105
website/flot/PLUGINS.txt Normal file
Просмотреть файл

@ -0,0 +1,105 @@
Writing plugins
---------------
To make a new plugin, create an init function and a set of options (if
needed), stuff it into an object and put it in the $.plot.plugins
array. For example:
function myCoolPluginInit(plot) { plot.coolstring = "Hello!" };
var myCoolOptions = { coolstuff: { show: true } }
$.plot.plugins.push({ init: myCoolPluginInit, options: myCoolOptions });
// now when $.plot is called, the returned object will have the
// attribute "coolstring"
Now, given that the plugin might run in many different places, it's
a good idea to avoid leaking names. We can avoid this by wrapping the
above lines in an anonymous function which we call immediately, like
this: (function () { inner code ... })(). To make it even more robust
in case $ is not bound to jQuery but some other Javascript library, we
can write it as
(function ($) {
// plugin definition
// ...
})(jQuery);
Here is a simple debug plugin which alerts each of the series in the
plot. It has a single option that control whether it is enabled and
how much info to output:
(function ($) {
function init(plot) {
var debugLevel = 1;
function checkDebugEnabled(plot, options) {
if (options.debug) {
debugLevel = options.debug;
plot.hooks.processDatapoints.push(alertSeries);
}
}
function alertSeries(plot, series, datapoints) {
var msg = "series " + series.label;
if (debugLevel > 1)
msg += " with " + series.data.length + " points";
alert(msg);
}
plot.hooks.processOptions.push(checkDebugEnabled);
}
var options = { debug: 0 };
$.plot.plugins.push({
init: init,
options: options,
name: "simpledebug",
version: "0.1"
});
})(jQuery);
We also define "name" and "version". It's not used by Flot, but might
be helpful for other plugins in resolving dependencies.
Put the above in a file named "jquery.flot.debug.js", include it in an
HTML page and then it can be used with:
$.plot($("#placeholder"), [...], { debug: 2 });
This simple plugin illustrates a couple of points:
- It uses the anonymous function trick to avoid name pollution.
- It can be enabled/disabled through an option.
- Variables in the init function can be used to store plot-specific
state between the hooks.
Options guidelines
==================
Plugins should always support appropriate options to enable/disable
them because the plugin user may have several plots on the same page
where only one should use the plugin.
If the plugin needs series-specific options, you can put them in
"series" in the options object, e.g.
var options = {
series: {
downsample: {
algorithm: null,
maxpoints: 1000
}
}
}
Then they will be copied by Flot into each series, providing the
defaults in case the plugin user doesn't specify any. Again, in most
cases it's probably a good idea if the plugin is turned off rather
than on per default, just like most of the powerful features in Flot.
Think hard and long about naming the options. These names are going to
be public API, and code is going to depend on them if the plugin is
successful.

81
website/flot/README.txt Normal file
Просмотреть файл

@ -0,0 +1,81 @@
About
-----
Flot is a Javascript plotting library for jQuery. Read more at the
website:
http://code.google.com/p/flot/
Take a look at the examples linked from above, they should give a good
impression of what Flot can do and the source code of the examples is
probably the fastest way to learn how to use Flot.
Installation
------------
Just include the Javascript file after you've included jQuery.
Note that you need to get a version of Excanvas (e.g. the one bundled
with Flot) which is canvas emulation on Internet Explorer. You can
include the excanvas script like this:
<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.pack.js"></script><![endif]-->
If it's not working on your development IE 6.0, check that it has
support for VML which excanvas is relying on. It appears that some
stripped down versions used for test environments on virtual machines
lack the VML support.
Also note that you need at least jQuery 1.2.6 (but at least jQuery
1.3.2 is recommended for interactive charts because of performance
improvements in event handling).
Basic usage
-----------
Create a placeholder div to put the graph in:
<div id="placeholder"></div>
You need to set the width and height of this div, otherwise the plot
library doesn't know how to scale the graph. You can do it inline like
this:
<div id="placeholder" style="width:600px;height:300px"></div>
You can also do it with an external stylesheet. Make sure that the
placeholder isn't within something with a display:none CSS property -
in that case, Flot has trouble measuring label dimensions which
results in garbled looks and might have trouble measuring the
placeholder dimensions which is fatal (it'll throw an exception).
Then when the div is ready in the DOM, which is usually on document
ready, run the plot function:
$.plot($("#placeholder"), data, options);
Here, data is an array of data series and options is an object with
settings if you want to customize the plot. Take a look at the
examples for some ideas of what to put in or look at the reference
in the file "API.txt". Here's a quick example that'll draw a line from
(0, 0) to (1, 1):
$.plot($("#placeholder"), [ [[0, 0], [1, 1]] ], { yaxis: { max: 1 } });
The plot function immediately draws the chart and then returns a plot
object with a couple of methods.
What's with the name?
---------------------
First: it's pronounced with a short o, like "plot". Not like "flawed".
So "Flot" rhymes with "plot".
And if you look up "flot" in a Danish-to-English dictionary, some up
the words that come up are "good-looking", "attractive", "stylish",
"smart", "impressive", "extravagant". One of the main goals with Flot
is pretty looks.

1427
website/flot/excanvas.js Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1
website/flot/excanvas.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -0,0 +1,174 @@
/* Plugin for jQuery for working with colors.
*
* Version 1.0.
*
* Inspiration from jQuery color animation plugin by John Resig.
*
* Released under the MIT license by Ole Laursen, October 2009.
*
* Examples:
*
* $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
* var c = $.color.extract($("#mydiv"), 'background-color');
* console.log(c.r, c.g, c.b, c.a);
* $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
*
* Note that .scale() and .add() work in-place instead of returning
* new objects.
*/
(function() {
jQuery.color = {};
// construct color object with some convenient chainable helpers
jQuery.color.make = function (r, g, b, a) {
var o = {};
o.r = r || 0;
o.g = g || 0;
o.b = b || 0;
o.a = a != null ? a : 1;
o.add = function (c, d) {
for (var i = 0; i < c.length; ++i)
o[c.charAt(i)] += d;
return o.normalize();
};
o.scale = function (c, f) {
for (var i = 0; i < c.length; ++i)
o[c.charAt(i)] *= f;
return o.normalize();
};
o.toString = function () {
if (o.a >= 1.0) {
return "rgb("+[o.r, o.g, o.b].join(",")+")";
} else {
return "rgba("+[o.r, o.g, o.b, o.a].join(",")+")";
}
};
o.normalize = function () {
function clamp(min, value, max) {
return value < min ? min: (value > max ? max: value);
}
o.r = clamp(0, parseInt(o.r), 255);
o.g = clamp(0, parseInt(o.g), 255);
o.b = clamp(0, parseInt(o.b), 255);
o.a = clamp(0, o.a, 1);
return o;
};
o.clone = function () {
return jQuery.color.make(o.r, o.b, o.g, o.a);
};
return o.normalize();
}
// extract CSS color property from element, going up in the DOM
// if it's "transparent"
jQuery.color.extract = function (elem, css) {
var c;
do {
c = elem.css(css).toLowerCase();
// keep going until we find an element that has color, or
// we hit the body
if (c != '' && c != 'transparent')
break;
elem = elem.parent();
} while (!jQuery.nodeName(elem.get(0), "body"));
// catch Safari's way of signalling transparent
if (c == "rgba(0, 0, 0, 0)")
c = "transparent";
return jQuery.color.parse(c);
}
// parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
// returns color object
jQuery.color.parse = function (str) {
var res, m = jQuery.color.make;
// Look for rgb(num,num,num)
if (res = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10));
// Look for rgba(num,num,num,num)
if (res = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10), parseFloat(res[4]));
// Look for rgb(num%,num%,num%)
if (res = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55);
// Look for rgba(num%,num%,num%,num)
if (res = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55, parseFloat(res[4]));
// Look for #a0b1c2
if (res = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
return m(parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16));
// Look for #fff
if (res = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
return m(parseInt(res[1]+res[1], 16), parseInt(res[2]+res[2], 16), parseInt(res[3]+res[3], 16));
// Otherwise, we're most likely dealing with a named color
var name = jQuery.trim(str).toLowerCase();
if (name == "transparent")
return m(255, 255, 255, 0);
else {
res = lookupColors[name];
return m(res[0], res[1], res[2]);
}
}
var lookupColors = {
aqua:[0,255,255],
azure:[240,255,255],
beige:[245,245,220],
black:[0,0,0],
blue:[0,0,255],
brown:[165,42,42],
cyan:[0,255,255],
darkblue:[0,0,139],
darkcyan:[0,139,139],
darkgrey:[169,169,169],
darkgreen:[0,100,0],
darkkhaki:[189,183,107],
darkmagenta:[139,0,139],
darkolivegreen:[85,107,47],
darkorange:[255,140,0],
darkorchid:[153,50,204],
darkred:[139,0,0],
darksalmon:[233,150,122],
darkviolet:[148,0,211],
fuchsia:[255,0,255],
gold:[255,215,0],
green:[0,128,0],
indigo:[75,0,130],
khaki:[240,230,140],
lightblue:[173,216,230],
lightcyan:[224,255,255],
lightgreen:[144,238,144],
lightgrey:[211,211,211],
lightpink:[255,182,193],
lightyellow:[255,255,224],
lime:[0,255,0],
magenta:[255,0,255],
maroon:[128,0,0],
navy:[0,0,128],
olive:[128,128,0],
orange:[255,165,0],
pink:[255,192,203],
purple:[128,0,128],
violet:[128,0,128],
red:[255,0,0],
silver:[192,192,192],
white:[255,255,255],
yellow:[255,255,0]
};
})();

1
website/flot/jquery.colorhelpers.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();

Просмотреть файл

@ -0,0 +1,156 @@
/*
Flot plugin for showing a crosshair, thin lines, when the mouse hovers
over the plot.
crosshair: {
mode: null or "x" or "y" or "xy"
color: color
lineWidth: number
}
Set the mode to one of "x", "y" or "xy". The "x" mode enables a
vertical crosshair that lets you trace the values on the x axis, "y"
enables a horizontal crosshair and "xy" enables them both. "color" is
the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
"lineWidth" is the width of the drawn lines (default is 1).
The plugin also adds four public methods:
- setCrosshair(pos)
Set the position of the crosshair. Note that this is cleared if
the user moves the mouse. "pos" should be on the form { x: xpos,
y: ypos } (or x2 and y2 if you're using the secondary axes), which
is coincidentally the same format as what you get from a "plothover"
event. If "pos" is null, the crosshair is cleared.
- clearCrosshair()
Clear the crosshair.
- lockCrosshair(pos)
Cause the crosshair to lock to the current location, no longer
updating if the user moves the mouse. Optionally supply a position
(passed on to setCrosshair()) to move it to.
Example usage:
var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
$("#graph").bind("plothover", function (evt, position, item) {
if (item) {
// Lock the crosshair to the data point being hovered
myFlot.lockCrosshair({ x: item.datapoint[0], y: item.datapoint[1] });
}
else {
// Return normal crosshair operation
myFlot.unlockCrosshair();
}
});
- unlockCrosshair()
Free the crosshair to move again after locking it.
*/
(function ($) {
var options = {
crosshair: {
mode: null, // one of null, "x", "y" or "xy",
color: "rgba(170, 0, 0, 0.80)",
lineWidth: 1
}
};
function init(plot) {
// position of crosshair in pixels
var crosshair = { x: -1, y: -1, locked: false };
plot.setCrosshair = function setCrosshair(pos) {
if (!pos)
crosshair.x = -1;
else {
var axes = plot.getAxes();
crosshair.x = Math.max(0, Math.min(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plot.width()));
crosshair.y = Math.max(0, Math.min(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plot.height()));
}
plot.triggerRedrawOverlay();
};
plot.clearCrosshair = plot.setCrosshair; // passes null for pos
plot.lockCrosshair = function lockCrosshair(pos) {
if (pos)
plot.setCrosshair(pos);
crosshair.locked = true;
}
plot.unlockCrosshair = function unlockCrosshair() {
crosshair.locked = false;
}
plot.hooks.bindEvents.push(function (plot, eventHolder) {
if (!plot.getOptions().crosshair.mode)
return;
eventHolder.mouseout(function () {
if (crosshair.x != -1) {
crosshair.x = -1;
plot.triggerRedrawOverlay();
}
});
eventHolder.mousemove(function (e) {
if (plot.getSelection && plot.getSelection()) {
crosshair.x = -1; // hide the crosshair while selecting
return;
}
if (crosshair.locked)
return;
var offset = plot.offset();
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
plot.triggerRedrawOverlay();
});
});
plot.hooks.drawOverlay.push(function (plot, ctx) {
var c = plot.getOptions().crosshair;
if (!c.mode)
return;
var plotOffset = plot.getPlotOffset();
ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);
if (crosshair.x != -1) {
ctx.strokeStyle = c.color;
ctx.lineWidth = c.lineWidth;
ctx.lineJoin = "round";
ctx.beginPath();
if (c.mode.indexOf("x") != -1) {
ctx.moveTo(crosshair.x, 0);
ctx.lineTo(crosshair.x, plot.height());
}
if (c.mode.indexOf("y") != -1) {
ctx.moveTo(0, crosshair.y);
ctx.lineTo(plot.width(), crosshair.y);
}
ctx.stroke();
}
ctx.restore();
});
}
$.plot.plugins.push({
init: init,
options: options,
name: 'crosshair',
version: '1.0'
});
})(jQuery);

1
website/flot/jquery.flot.crosshair.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(B){var A={crosshair:{mode:null,color:"rgba(170, 0, 0, 0.80)",lineWidth:1}};function C(G){var H={x:-1,y:-1,locked:false};G.setCrosshair=function D(J){if(!J){H.x=-1}else{var I=G.getAxes();H.x=Math.max(0,Math.min(J.x!=null?I.xaxis.p2c(J.x):I.x2axis.p2c(J.x2),G.width()));H.y=Math.max(0,Math.min(J.y!=null?I.yaxis.p2c(J.y):I.y2axis.p2c(J.y2),G.height()))}G.triggerRedrawOverlay()};G.clearCrosshair=G.setCrosshair;G.lockCrosshair=function E(I){if(I){G.setCrosshair(I)}H.locked=true};G.unlockCrosshair=function F(){H.locked=false};G.hooks.bindEvents.push(function(J,I){if(!J.getOptions().crosshair.mode){return }I.mouseout(function(){if(H.x!=-1){H.x=-1;J.triggerRedrawOverlay()}});I.mousemove(function(K){if(J.getSelection&&J.getSelection()){H.x=-1;return }if(H.locked){return }var L=J.offset();H.x=Math.max(0,Math.min(K.pageX-L.left,J.width()));H.y=Math.max(0,Math.min(K.pageY-L.top,J.height()));J.triggerRedrawOverlay()})});G.hooks.drawOverlay.push(function(K,I){var L=K.getOptions().crosshair;if(!L.mode){return }var J=K.getPlotOffset();I.save();I.translate(J.left,J.top);if(H.x!=-1){I.strokeStyle=L.color;I.lineWidth=L.lineWidth;I.lineJoin="round";I.beginPath();if(L.mode.indexOf("x")!=-1){I.moveTo(H.x,0);I.lineTo(H.x,K.height())}if(L.mode.indexOf("y")!=-1){I.moveTo(0,H.y);I.lineTo(K.width(),H.y)}I.stroke()}I.restore()})}B.plot.plugins.push({init:C,options:A,name:"crosshair",version:"1.0"})})(jQuery);

Просмотреть файл

@ -0,0 +1,237 @@
/*
Flot plugin for plotting images, e.g. useful for putting ticks on a
prerendered complex visualization.
The data syntax is [[image, x1, y1, x2, y2], ...] where (x1, y1) and
(x2, y2) are where you intend the two opposite corners of the image to
end up in the plot. Image must be a fully loaded Javascript image (you
can make one with new Image()). If the image is not complete, it's
skipped when plotting.
There are two helpers included for retrieving images. The easiest work
the way that you put in URLs instead of images in the data (like
["myimage.png", 0, 0, 10, 10]), then call $.plot.image.loadData(data,
options, callback) where data and options are the same as you pass in
to $.plot. This loads the images, replaces the URLs in the data with
the corresponding images and calls "callback" when all images are
loaded (or failed loading). In the callback, you can then call $.plot
with the data set. See the included example.
A more low-level helper, $.plot.image.load(urls, callback) is also
included. Given a list of URLs, it calls callback with an object
mapping from URL to Image object when all images are loaded or have
failed loading.
Options for the plugin are
series: {
images: {
show: boolean
anchor: "corner" or "center"
alpha: [0,1]
}
}
which can be specified for a specific series
$.plot($("#placeholder"), [{ data: [ ... ], images: { ... } ])
Note that because the data format is different from usual data points,
you can't use images with anything else in a specific data series.
Setting "anchor" to "center" causes the pixels in the image to be
anchored at the corner pixel centers inside of at the pixel corners,
effectively letting half a pixel stick out to each side in the plot.
A possible future direction could be support for tiling for large
images (like Google Maps).
*/
(function ($) {
var options = {
series: {
images: {
show: false,
alpha: 1,
anchor: "corner" // or "center"
}
}
};
$.plot.image = {};
$.plot.image.loadDataImages = function (series, options, callback) {
var urls = [], points = [];
var defaultShow = options.series.images.show;
$.each(series, function (i, s) {
if (!(defaultShow || s.images.show))
return;
if (s.data)
s = s.data;
$.each(s, function (i, p) {
if (typeof p[0] == "string") {
urls.push(p[0]);
points.push(p);
}
});
});
$.plot.image.load(urls, function (loadedImages) {
$.each(points, function (i, p) {
var url = p[0];
if (loadedImages[url])
p[0] = loadedImages[url];
});
callback();
});
}
$.plot.image.load = function (urls, callback) {
var missing = urls.length, loaded = {};
if (missing == 0)
callback({});
$.each(urls, function (i, url) {
var handler = function () {
--missing;
loaded[url] = this;
if (missing == 0)
callback(loaded);
};
$('<img />').load(handler).error(handler).attr('src', url);
});
}
function draw(plot, ctx) {
var plotOffset = plot.getPlotOffset();
$.each(plot.getData(), function (i, series) {
var points = series.datapoints.points,
ps = series.datapoints.pointsize;
for (var i = 0; i < points.length; i += ps) {
var img = points[i],
x1 = points[i + 1], y1 = points[i + 2],
x2 = points[i + 3], y2 = points[i + 4],
xaxis = series.xaxis, yaxis = series.yaxis,
tmp;
// actually we should check img.complete, but it
// appears to be a somewhat unreliable indicator in
// IE6 (false even after load event)
if (!img || img.width <= 0 || img.height <= 0)
continue;
if (x1 > x2) {
tmp = x2;
x2 = x1;
x1 = tmp;
}
if (y1 > y2) {
tmp = y2;
y2 = y1;
y1 = tmp;
}
// if the anchor is at the center of the pixel, expand the
// image by 1/2 pixel in each direction
if (series.images.anchor == "center") {
tmp = 0.5 * (x2-x1) / (img.width - 1);
x1 -= tmp;
x2 += tmp;
tmp = 0.5 * (y2-y1) / (img.height - 1);
y1 -= tmp;
y2 += tmp;
}
// clip
if (x1 == x2 || y1 == y2 ||
x1 >= xaxis.max || x2 <= xaxis.min ||
y1 >= yaxis.max || y2 <= yaxis.min)
continue;
var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
if (x1 < xaxis.min) {
sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
x1 = xaxis.min;
}
if (x2 > xaxis.max) {
sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
x2 = xaxis.max;
}
if (y1 < yaxis.min) {
sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
y1 = yaxis.min;
}
if (y2 > yaxis.max) {
sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
y2 = yaxis.max;
}
x1 = xaxis.p2c(x1);
x2 = xaxis.p2c(x2);
y1 = yaxis.p2c(y1);
y2 = yaxis.p2c(y2);
// the transformation may have swapped us
if (x1 > x2) {
tmp = x2;
x2 = x1;
x1 = tmp;
}
if (y1 > y2) {
tmp = y2;
y2 = y1;
y1 = tmp;
}
tmp = ctx.globalAlpha;
ctx.globalAlpha *= series.images.alpha;
ctx.drawImage(img,
sx1, sy1, sx2 - sx1, sy2 - sy1,
x1 + plotOffset.left, y1 + plotOffset.top,
x2 - x1, y2 - y1);
ctx.globalAlpha = tmp;
}
});
}
function processRawData(plot, series, data, datapoints) {
if (!series.images.show)
return;
// format is Image, x1, y1, x2, y2 (opposite corners)
datapoints.format = [
{ required: true },
{ x: true, number: true, required: true },
{ y: true, number: true, required: true },
{ x: true, number: true, required: true },
{ y: true, number: true, required: true }
];
}
function init(plot) {
plot.hooks.processRawData.push(processRawData);
plot.hooks.draw.push(draw);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'image',
version: '1.1'
});
})(jQuery);

1
website/flot/jquery.flot.image.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(D){var B={series:{images:{show:false,alpha:1,anchor:"corner"}}};D.plot.image={};D.plot.image.loadDataImages=function(G,F,K){var J=[],H=[];var I=F.series.images.show;D.each(G,function(L,M){if(!(I||M.images.show)){return }if(M.data){M=M.data}D.each(M,function(N,O){if(typeof O[0]=="string"){J.push(O[0]);H.push(O)}})});D.plot.image.load(J,function(L){D.each(H,function(N,O){var M=O[0];if(L[M]){O[0]=L[M]}});K()})};D.plot.image.load=function(H,I){var G=H.length,F={};if(G==0){I({})}D.each(H,function(K,J){var L=function(){--G;F[J]=this;if(G==0){I(F)}};D("<img />").load(L).error(L).attr("src",J)})};function A(H,F){var G=H.getPlotOffset();D.each(H.getData(),function(O,P){var X=P.datapoints.points,I=P.datapoints.pointsize;for(var O=0;O<X.length;O+=I){var Q=X[O],M=X[O+1],V=X[O+2],K=X[O+3],T=X[O+4],W=P.xaxis,S=P.yaxis,N;if(!Q||Q.width<=0||Q.height<=0){continue}if(M>K){N=K;K=M;M=N}if(V>T){N=T;T=V;V=N}if(P.images.anchor=="center"){N=0.5*(K-M)/(Q.width-1);M-=N;K+=N;N=0.5*(T-V)/(Q.height-1);V-=N;T+=N}if(M==K||V==T||M>=W.max||K<=W.min||V>=S.max||T<=S.min){continue}var L=0,U=0,J=Q.width,R=Q.height;if(M<W.min){L+=(J-L)*(W.min-M)/(K-M);M=W.min}if(K>W.max){J+=(J-L)*(W.max-K)/(K-M);K=W.max}if(V<S.min){R+=(U-R)*(S.min-V)/(T-V);V=S.min}if(T>S.max){U+=(U-R)*(S.max-T)/(T-V);T=S.max}M=W.p2c(M);K=W.p2c(K);V=S.p2c(V);T=S.p2c(T);if(M>K){N=K;K=M;M=N}if(V>T){N=T;T=V;V=N}N=F.globalAlpha;F.globalAlpha*=P.images.alpha;F.drawImage(Q,L,U,J-L,R-U,M+G.left,V+G.top,K-M,T-V);F.globalAlpha=N}})}function C(I,F,G,H){if(!F.images.show){return }H.format=[{required:true},{x:true,number:true,required:true},{y:true,number:true,required:true},{x:true,number:true,required:true},{y:true,number:true,required:true}]}function E(F){F.hooks.processRawData.push(C);F.hooks.draw.push(A)}D.plot.plugins.push({init:E,options:B,name:"image",version:"1.1"})})(jQuery);

2127
website/flot/jquery.flot.js Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1
website/flot/jquery.flot.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -0,0 +1,272 @@
/*
Flot plugin for adding panning and zooming capabilities to a plot.
The default behaviour is double click and scrollwheel up/down to zoom
in, drag to pan. The plugin defines plot.zoom({ center }),
plot.zoomOut() and plot.pan(offset) so you easily can add custom
controls. It also fires a "plotpan" and "plotzoom" event when
something happens, useful for synchronizing plots.
Example usage:
plot = $.plot(...);
// zoom default amount in on the pixel (100, 200)
plot.zoom({ center: { left: 10, top: 20 } });
// zoom out again
plot.zoomOut({ center: { left: 10, top: 20 } });
// pan 100 pixels to the left and 20 down
plot.pan({ left: -100, top: 20 })
Options:
zoom: {
interactive: false
trigger: "dblclick" // or "click" for single click
amount: 1.5 // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
}
pan: {
interactive: false
}
xaxis, yaxis, x2axis, y2axis: {
zoomRange: null // or [number, number] (min range, max range)
panRange: null // or [number, number] (min, max)
}
"interactive" enables the built-in drag/click behaviour. "amount" is
the amount to zoom the viewport relative to the current range, so 1 is
100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out).
"zoomRange" is the interval in which zooming can happen, e.g. with
zoomRange: [1, 100] the zoom will never scale the axis so that the
difference between min and max is smaller than 1 or larger than 100.
You can set either of them to null to ignore.
"panRange" confines the panning to stay within a range, e.g. with
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
other. Either can be null.
*/
// First two dependencies, jquery.event.drag.js and
// jquery.mousewheel.js, we put them inline here to save people the
// effort of downloading them.
/*
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
*/
(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);
/* jquery.mousewheel.min.js
* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
*
* Version: 3.0.2
*
* Requires: 1.2.2+
*/
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);
(function ($) {
var options = {
xaxis: {
zoomRange: null, // or [number, number] (min range, max range)
panRange: null // or [number, number] (min, max)
},
zoom: {
interactive: false,
trigger: "dblclick", // or "click" for single click
amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
},
pan: {
interactive: false
}
};
function init(plot) {
function bindEvents(plot, eventHolder) {
var o = plot.getOptions();
if (o.zoom.interactive) {
function clickHandler(e, zoomOut) {
var c = plot.offset();
c.left = e.pageX - c.left;
c.top = e.pageY - c.top;
if (zoomOut)
plot.zoomOut({ center: c });
else
plot.zoom({ center: c });
}
eventHolder[o.zoom.trigger](clickHandler);
eventHolder.mousewheel(function (e, delta) {
clickHandler(e, delta < 0);
return false;
});
}
if (o.pan.interactive) {
var prevCursor = 'default', pageX = 0, pageY = 0;
eventHolder.bind("dragstart", { distance: 10 }, function (e) {
if (e.which != 1) // only accept left-click
return false;
eventHolderCursor = eventHolder.css('cursor');
eventHolder.css('cursor', 'move');
pageX = e.pageX;
pageY = e.pageY;
});
eventHolder.bind("drag", function (e) {
// unused at the moment, but we need it here to
// trigger the dragstart/dragend events
});
eventHolder.bind("dragend", function (e) {
eventHolder.css('cursor', prevCursor);
plot.pan({ left: pageX - e.pageX,
top: pageY - e.pageY });
});
}
}
plot.zoomOut = function (args) {
if (!args)
args = {};
if (!args.amount)
args.amount = plot.getOptions().zoom.amount
args.amount = 1 / args.amount;
plot.zoom(args);
}
plot.zoom = function (args) {
if (!args)
args = {};
var axes = plot.getAxes(),
options = plot.getOptions(),
c = args.center,
amount = args.amount ? args.amount : options.zoom.amount,
w = plot.width(), h = plot.height();
if (!c)
c = { left: w / 2, top: h / 2 };
var xf = c.left / w,
x1 = c.left - xf * w / amount,
x2 = c.left + (1 - xf) * w / amount,
yf = c.top / h,
y1 = c.top - yf * h / amount,
y2 = c.top + (1 - yf) * h / amount;
function scaleAxis(min, max, name) {
var axis = axes[name],
axisOptions = options[name];
if (!axis.used)
return;
min = axis.c2p(min);
max = axis.c2p(max);
if (max < min) { // make sure min < max
var tmp = min
min = max;
max = tmp;
}
var range = max - min, zr = axisOptions.zoomRange;
if (zr &&
((zr[0] != null && range < zr[0]) ||
(zr[1] != null && range > zr[1])))
return;
axisOptions.min = min;
axisOptions.max = max;
}
scaleAxis(x1, x2, 'xaxis');
scaleAxis(x1, x2, 'x2axis');
scaleAxis(y1, y2, 'yaxis');
scaleAxis(y1, y2, 'y2axis');
plot.setupGrid();
plot.draw();
if (!args.preventEvent)
plot.getPlaceholder().trigger("plotzoom", [ plot ]);
}
plot.pan = function (args) {
var l = +args.left, t = +args.top,
axes = plot.getAxes(), options = plot.getOptions();
if (isNaN(l))
l = 0;
if (isNaN(t))
t = 0;
function panAxis(delta, name) {
var axis = axes[name],
axisOptions = options[name],
min, max;
if (!axis.used)
return;
min = axis.c2p(axis.p2c(axis.min) + delta),
max = axis.c2p(axis.p2c(axis.max) + delta);
var pr = axisOptions.panRange;
if (pr) {
// check whether we hit the wall
if (pr[0] != null && pr[0] > min) {
delta = pr[0] - min;
min += delta;
max += delta;
}
if (pr[1] != null && pr[1] < max) {
delta = pr[1] - max;
min += delta;
max += delta;
}
}
axisOptions.min = min;
axisOptions.max = max;
}
panAxis(l, 'xaxis');
panAxis(l, 'x2axis');
panAxis(t, 'yaxis');
panAxis(t, 'y2axis');
plot.setupGrid();
plot.draw();
if (!args.preventEvent)
plot.getPlaceholder().trigger("plotpan", [ plot ]);
}
plot.hooks.bindEvents.push(bindEvents);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'navigate',
version: '1.1'
});
})(jQuery);

1
website/flot/jquery.flot.navigate.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(R){R.fn.drag=function(A,B,C){if(B){this.bind("dragstart",A)}if(C){this.bind("dragend",C)}return !A?this.trigger("drag"):this.bind("drag",B?B:A)};var M=R.event,L=M.special,Q=L.drag={not:":input",distance:0,which:1,dragging:false,setup:function(A){A=R.extend({distance:Q.distance,which:Q.which,not:Q.not},A||{});A.distance=N(A.distance);M.add(this,"mousedown",O,A);if(this.attachEvent){this.attachEvent("ondragstart",J)}},teardown:function(){M.remove(this,"mousedown",O);if(this===Q.dragging){Q.dragging=Q.proxy=false}P(this,true);if(this.detachEvent){this.detachEvent("ondragstart",J)}}};L.dragstart=L.dragend={setup:function(){},teardown:function(){}};function O(A){var B=this,C,D=A.data||{};if(D.elem){B=A.dragTarget=D.elem;A.dragProxy=Q.proxy||B;A.cursorOffsetX=D.pageX-D.left;A.cursorOffsetY=D.pageY-D.top;A.offsetX=A.pageX-A.cursorOffsetX;A.offsetY=A.pageY-A.cursorOffsetY}else{if(Q.dragging||(D.which>0&&A.which!=D.which)||R(A.target).is(D.not)){return }}switch(A.type){case"mousedown":R.extend(D,R(B).offset(),{elem:B,target:A.target,pageX:A.pageX,pageY:A.pageY});M.add(document,"mousemove mouseup",O,D);P(B,false);Q.dragging=null;return false;case !Q.dragging&&"mousemove":if(N(A.pageX-D.pageX)+N(A.pageY-D.pageY)<D.distance){break}A.target=D.target;C=K(A,"dragstart",B);if(C!==false){Q.dragging=B;Q.proxy=A.dragProxy=R(C||B)[0]}case"mousemove":if(Q.dragging){C=K(A,"drag",B);if(L.drop){L.drop.allowed=(C!==false);L.drop.handler(A)}if(C!==false){break}A.type="mouseup"}case"mouseup":M.remove(document,"mousemove mouseup",O);if(Q.dragging){if(L.drop){L.drop.handler(A)}K(A,"dragend",B)}P(B,true);Q.dragging=Q.proxy=D.elem=false;break}return true}function K(D,B,A){D.type=B;var C=R.event.handle.call(A,D);return C===false?false:C||D.result}function N(A){return Math.pow(A,2)}function J(){return(Q.dragging===false)}function P(A,B){if(!A){return }A.unselectable=B?"off":"on";A.onselectstart=function(){return B};if(A.style){A.style.MozUserSelect=B?"":"none"}}})(jQuery);(function(C){var B=["DOMMouseScroll","mousewheel"];C.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var D=B.length;D;){this.addEventListener(B[--D],A,false)}}else{this.onmousewheel=A}},teardown:function(){if(this.removeEventListener){for(var D=B.length;D;){this.removeEventListener(B[--D],A,false)}}else{this.onmousewheel=null}}};C.fn.extend({mousewheel:function(D){return D?this.bind("mousewheel",D):this.trigger("mousewheel")},unmousewheel:function(D){return this.unbind("mousewheel",D)}});function A(E){var G=[].slice.call(arguments,1),D=0,F=true;E=C.event.fix(E||window.event);E.type="mousewheel";if(E.wheelDelta){D=E.wheelDelta/120}if(E.detail){D=-E.detail/3}G.unshift(E,D);return C.event.handle.apply(this,G)}})(jQuery);(function(B){var A={xaxis:{zoomRange:null,panRange:null},zoom:{interactive:false,trigger:"dblclick",amount:1.5},pan:{interactive:false}};function C(D){function E(J,F){var K=J.getOptions();if(K.zoom.interactive){function L(N,M){var O=J.offset();O.left=N.pageX-O.left;O.top=N.pageY-O.top;if(M){J.zoomOut({center:O})}else{J.zoom({center:O})}}F[K.zoom.trigger](L);F.mousewheel(function(M,N){L(M,N<0);return false})}if(K.pan.interactive){var I="default",H=0,G=0;F.bind("dragstart",{distance:10},function(M){if(M.which!=1){return false}eventHolderCursor=F.css("cursor");F.css("cursor","move");H=M.pageX;G=M.pageY});F.bind("drag",function(M){});F.bind("dragend",function(M){F.css("cursor",I);J.pan({left:H-M.pageX,top:G-M.pageY})})}}D.zoomOut=function(F){if(!F){F={}}if(!F.amount){F.amount=D.getOptions().zoom.amount}F.amount=1/F.amount;D.zoom(F)};D.zoom=function(M){if(!M){M={}}var L=D.getAxes(),S=D.getOptions(),N=M.center,J=M.amount?M.amount:S.zoom.amount,R=D.width(),I=D.height();if(!N){N={left:R/2,top:I/2}}var Q=N.left/R,G=N.left-Q*R/J,F=N.left+(1-Q)*R/J,H=N.top/I,P=N.top-H*I/J,O=N.top+(1-H)*I/J;function K(X,T,V){var Y=L[V],a=S[V];if(!Y.used){return }X=Y.c2p(X);T=Y.c2p(T);if(T<X){var W=X;X=T;T=W}var U=T-X,Z=a.zoomRange;if(Z&&((Z[0]!=null&&U<Z[0])||(Z[1]!=null&&U>Z[1]))){return }a.min=X;a.max=T}K(G,F,"xaxis");K(G,F,"x2axis");K(P,O,"yaxis");K(P,O,"y2axis");D.setupGrid();D.draw();if(!M.preventEvent){D.getPlaceholder().trigger("plotzoom",[D])}};D.pan=function(I){var F=+I.left,J=+I.top,K=D.getAxes(),H=D.getOptions();if(isNaN(F)){F=0}if(isNaN(J)){J=0}function G(R,M){var O=K[M],Q=H[M],N,L;if(!O.used){return }N=O.c2p(O.p2c(O.min)+R),L=O.c2p(O.p2c(O.max)+R);var P=Q.panRange;if(P){if(P[0]!=null&&P[0]>N){R=P[0]-N;N+=R;L+=R}if(P[1]!=null&&P[1]<L){R=P[1]-L;N+=R;L+=R}}Q.min=N;Q.max=L}G(F,"xaxis");G(F,"x2axis");G(J,"yaxis");G(J,"y2axis");D.setupGrid();D.draw();if(!I.preventEvent){D.getPlaceholder().trigger("plotpan",[D])}};D.hooks.bindEvents.push(E)}B.plot.plugins.push({init:C,options:A,name:"navigate",version:"1.1"})})(jQuery);

Просмотреть файл

@ -0,0 +1,299 @@
/*
Flot plugin for selecting regions.
The plugin defines the following options:
selection: {
mode: null or "x" or "y" or "xy",
color: color
}
You enable selection support by setting the mode to one of "x", "y" or
"xy". In "x" mode, the user will only be able to specify the x range,
similarly for "y" mode. For "xy", the selection becomes a rectangle
where both ranges can be specified. "color" is color of the selection.
When selection support is enabled, a "plotselected" event will be emitted
on the DOM element you passed into the plot function. The event
handler gets one extra parameter with the ranges selected on the axes,
like this:
placeholder.bind("plotselected", function(event, ranges) {
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
// similar for yaxis, secondary axes are in x2axis
// and y2axis if present
});
The "plotselected" event is only fired when the user has finished
making the selection. A "plotselecting" event is fired during the
process with the same parameters as the "plotselected" event, in case
you want to know what's happening while it's happening,
A "plotunselected" event with no arguments is emitted when the user
clicks the mouse to remove the selection.
The plugin allso adds the following methods to the plot object:
- setSelection(ranges, preventEvent)
Set the selection rectangle. The passed in ranges is on the same
form as returned in the "plotselected" event. If the selection
mode is "x", you should put in either an xaxis (or x2axis) object,
if the mode is "y" you need to put in an yaxis (or y2axis) object
and both xaxis/x2axis and yaxis/y2axis if the selection mode is
"xy", like this:
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
setSelection will trigger the "plotselected" event when called. If
you don't want that to happen, e.g. if you're inside a
"plotselected" handler, pass true as the second parameter.
- clearSelection(preventEvent)
Clear the selection rectangle. Pass in true to avoid getting a
"plotunselected" event.
- getSelection()
Returns the current selection in the same format as the
"plotselected" event. If there's currently no selection, the
function returns null.
*/
(function ($) {
function init(plot) {
var selection = {
first: { x: -1, y: -1}, second: { x: -1, y: -1},
show: false,
active: false
};
// FIXME: The drag handling implemented here should be
// abstracted out, there's some similar code from a library in
// the navigation plugin, this should be massaged a bit to fit
// the Flot cases here better and reused. Doing this would
// make this plugin much slimmer.
var savedhandlers = {};
function onMouseMove(e) {
if (selection.active) {
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
updateSelection(e);
}
}
function onMouseDown(e) {
if (e.which != 1) // only accept left-click
return;
// cancel out any text selections
document.body.focus();
// prevent text selection and drag in old-school browsers
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
savedhandlers.onselectstart = document.onselectstart;
document.onselectstart = function () { return false; };
}
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
savedhandlers.ondrag = document.ondrag;
document.ondrag = function () { return false; };
}
setSelectionPos(selection.first, e);
selection.active = true;
$(document).one("mouseup", onMouseUp);
}
function onMouseUp(e) {
// revert drag stuff for old-school browsers
if (document.onselectstart !== undefined)
document.onselectstart = savedhandlers.onselectstart;
if (document.ondrag !== undefined)
document.ondrag = savedhandlers.ondrag;
// no more draggy-dee-drag
selection.active = false;
updateSelection(e);
if (selectionIsSane())
triggerSelectedEvent();
else {
// this counts as a clear
plot.getPlaceholder().trigger("plotunselected", [ ]);
plot.getPlaceholder().trigger("plotselecting", [ null ]);
}
return false;
}
function getSelection() {
if (!selectionIsSane())
return null;
var x1 = Math.min(selection.first.x, selection.second.x),
x2 = Math.max(selection.first.x, selection.second.x),
y1 = Math.max(selection.first.y, selection.second.y),
y2 = Math.min(selection.first.y, selection.second.y);
var r = {};
var axes = plot.getAxes();
if (axes.xaxis.used)
r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) };
if (axes.x2axis.used)
r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) };
if (axes.yaxis.used)
r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) };
if (axes.y2axis.used)
r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) };
return r;
}
function triggerSelectedEvent() {
var r = getSelection();
plot.getPlaceholder().trigger("plotselected", [ r ]);
// backwards-compat stuff, to be removed in future
var axes = plot.getAxes();
if (axes.xaxis.used && axes.yaxis.used)
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
}
function clamp(min, value, max) {
return value < min? min: (value > max? max: value);
}
function setSelectionPos(pos, e) {
var o = plot.getOptions();
var offset = plot.getPlaceholder().offset();
var plotOffset = plot.getPlotOffset();
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
if (o.selection.mode == "y")
pos.x = pos == selection.first? 0: plot.width();
if (o.selection.mode == "x")
pos.y = pos == selection.first? 0: plot.height();
}
function updateSelection(pos) {
if (pos.pageX == null)
return;
setSelectionPos(selection.second, pos);
if (selectionIsSane()) {
selection.show = true;
plot.triggerRedrawOverlay();
}
else
clearSelection(true);
}
function clearSelection(preventEvent) {
if (selection.show) {
selection.show = false;
plot.triggerRedrawOverlay();
if (!preventEvent)
plot.getPlaceholder().trigger("plotunselected", [ ]);
}
}
function setSelection(ranges, preventEvent) {
var axis, range, axes = plot.getAxes();
var o = plot.getOptions();
if (o.selection.mode == "y") {
selection.first.x = 0;
selection.second.x = plot.width();
}
else {
axis = ranges["xaxis"]? axes["xaxis"]: (ranges["x2axis"]? axes["x2axis"]: axes["xaxis"]);
range = ranges["xaxis"] || ranges["x2axis"] || { from:ranges["x1"], to:ranges["x2"] }
selection.first.x = axis.p2c(Math.min(range.from, range.to));
selection.second.x = axis.p2c(Math.max(range.from, range.to));
}
if (o.selection.mode == "x") {
selection.first.y = 0;
selection.second.y = plot.height();
}
else {
axis = ranges["yaxis"]? axes["yaxis"]: (ranges["y2axis"]? axes["y2axis"]: axes["yaxis"]);
range = ranges["yaxis"] || ranges["y2axis"] || { from:ranges["y1"], to:ranges["y2"] }
selection.first.y = axis.p2c(Math.min(range.from, range.to));
selection.second.y = axis.p2c(Math.max(range.from, range.to));
}
selection.show = true;
plot.triggerRedrawOverlay();
if (!preventEvent)
triggerSelectedEvent();
}
function selectionIsSane() {
var minSize = 5;
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
Math.abs(selection.second.y - selection.first.y) >= minSize;
}
plot.clearSelection = clearSelection;
plot.setSelection = setSelection;
plot.getSelection = getSelection;
plot.hooks.bindEvents.push(function(plot, eventHolder) {
var o = plot.getOptions();
if (o.selection.mode != null)
eventHolder.mousemove(onMouseMove);
if (o.selection.mode != null)
eventHolder.mousedown(onMouseDown);
});
plot.hooks.drawOverlay.push(function (plot, ctx) {
// draw selection
if (selection.show && selectionIsSane()) {
var plotOffset = plot.getPlotOffset();
var o = plot.getOptions();
ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);
var c = $.color.parse(o.selection.color);
ctx.strokeStyle = c.scale('a', 0.8).toString();
ctx.lineWidth = 1;
ctx.lineJoin = "round";
ctx.fillStyle = c.scale('a', 0.4).toString();
var x = Math.min(selection.first.x, selection.second.x),
y = Math.min(selection.first.y, selection.second.y),
w = Math.abs(selection.second.x - selection.first.x),
h = Math.abs(selection.second.y - selection.first.y);
ctx.fillRect(x, y, w, h);
ctx.strokeRect(x, y, w, h);
ctx.restore();
}
});
}
$.plot.plugins.push({
init: init,
options: {
selection: {
mode: null, // one of null, "x", "y" or "xy"
color: "#e8cfac"
}
},
name: 'selection',
version: '1.0'
});
})(jQuery);

1
website/flot/jquery.flot.selection.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(A){function B(J){var O={first:{x:-1,y:-1},second:{x:-1,y:-1},show:false,active:false};var L={};function D(Q){if(O.active){J.getPlaceholder().trigger("plotselecting",[F()]);K(Q)}}function M(Q){if(Q.which!=1){return }document.body.focus();if(document.onselectstart!==undefined&&L.onselectstart==null){L.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!==undefined&&L.ondrag==null){L.ondrag=document.ondrag;document.ondrag=function(){return false}}C(O.first,Q);O.active=true;A(document).one("mouseup",I)}function I(Q){if(document.onselectstart!==undefined){document.onselectstart=L.onselectstart}if(document.ondrag!==undefined){document.ondrag=L.ondrag}O.active=false;K(Q);if(E()){H()}else{J.getPlaceholder().trigger("plotunselected",[]);J.getPlaceholder().trigger("plotselecting",[null])}return false}function F(){if(!E()){return null}var R=Math.min(O.first.x,O.second.x),Q=Math.max(O.first.x,O.second.x),T=Math.max(O.first.y,O.second.y),S=Math.min(O.first.y,O.second.y);var U={};var V=J.getAxes();if(V.xaxis.used){U.xaxis={from:V.xaxis.c2p(R),to:V.xaxis.c2p(Q)}}if(V.x2axis.used){U.x2axis={from:V.x2axis.c2p(R),to:V.x2axis.c2p(Q)}}if(V.yaxis.used){U.yaxis={from:V.yaxis.c2p(T),to:V.yaxis.c2p(S)}}if(V.y2axis.used){U.y2axis={from:V.y2axis.c2p(T),to:V.y2axis.c2p(S)}}return U}function H(){var Q=F();J.getPlaceholder().trigger("plotselected",[Q]);var R=J.getAxes();if(R.xaxis.used&&R.yaxis.used){J.getPlaceholder().trigger("selected",[{x1:Q.xaxis.from,y1:Q.yaxis.from,x2:Q.xaxis.to,y2:Q.yaxis.to}])}}function G(R,S,Q){return S<R?R:(S>Q?Q:S)}function C(U,R){var T=J.getOptions();var S=J.getPlaceholder().offset();var Q=J.getPlotOffset();U.x=G(0,R.pageX-S.left-Q.left,J.width());U.y=G(0,R.pageY-S.top-Q.top,J.height());if(T.selection.mode=="y"){U.x=U==O.first?0:J.width()}if(T.selection.mode=="x"){U.y=U==O.first?0:J.height()}}function K(Q){if(Q.pageX==null){return }C(O.second,Q);if(E()){O.show=true;J.triggerRedrawOverlay()}else{P(true)}}function P(Q){if(O.show){O.show=false;J.triggerRedrawOverlay();if(!Q){J.getPlaceholder().trigger("plotunselected",[])}}}function N(R,Q){var T,S,U=J.getAxes();var V=J.getOptions();if(V.selection.mode=="y"){O.first.x=0;O.second.x=J.width()}else{T=R.xaxis?U.xaxis:(R.x2axis?U.x2axis:U.xaxis);S=R.xaxis||R.x2axis||{from:R.x1,to:R.x2};O.first.x=T.p2c(Math.min(S.from,S.to));O.second.x=T.p2c(Math.max(S.from,S.to))}if(V.selection.mode=="x"){O.first.y=0;O.second.y=J.height()}else{T=R.yaxis?U.yaxis:(R.y2axis?U.y2axis:U.yaxis);S=R.yaxis||R.y2axis||{from:R.y1,to:R.y2};O.first.y=T.p2c(Math.min(S.from,S.to));O.second.y=T.p2c(Math.max(S.from,S.to))}O.show=true;J.triggerRedrawOverlay();if(!Q){H()}}function E(){var Q=5;return Math.abs(O.second.x-O.first.x)>=Q&&Math.abs(O.second.y-O.first.y)>=Q}J.clearSelection=P;J.setSelection=N;J.getSelection=F;J.hooks.bindEvents.push(function(R,Q){var S=R.getOptions();if(S.selection.mode!=null){Q.mousemove(D)}if(S.selection.mode!=null){Q.mousedown(M)}});J.hooks.drawOverlay.push(function(T,Y){if(O.show&&E()){var R=T.getPlotOffset();var Q=T.getOptions();Y.save();Y.translate(R.left,R.top);var U=A.color.parse(Q.selection.color);Y.strokeStyle=U.scale("a",0.8).toString();Y.lineWidth=1;Y.lineJoin="round";Y.fillStyle=U.scale("a",0.4).toString();var W=Math.min(O.first.x,O.second.x),V=Math.min(O.first.y,O.second.y),X=Math.abs(O.second.x-O.first.x),S=Math.abs(O.second.y-O.first.y);Y.fillRect(W,V,X,S);Y.strokeRect(W,V,X,S);Y.restore()}})}A.plot.plugins.push({init:B,options:{selection:{mode:null,color:"#e8cfac"}},name:"selection",version:"1.0"})})(jQuery);

Просмотреть файл

@ -0,0 +1,152 @@
/*
Flot plugin for stacking data sets, i.e. putting them on top of each
other, for accumulative graphs. Note that the plugin assumes the data
is sorted on x. Also note that stacking a mix of positive and negative
values in most instances doesn't make sense (so it looks weird).
Two or more series are stacked when their "stack" attribute is set to
the same key (which can be any number or string or just "true"). To
specify the default stack, you can set
series: {
stack: null or true or key (number/string)
}
or specify it for a specific series
$.plot($("#placeholder"), [{ data: [ ... ], stack: true ])
The stacking order is determined by the order of the data series in
the array (later series end up on top of the previous).
Internally, the plugin modifies the datapoints in each series, adding
an offset to the y value. For line series, extra data points are
inserted through interpolation. For bar charts, the second y value is
also adjusted.
*/
(function ($) {
var options = {
series: { stack: null } // or number/string
};
function init(plot) {
function findMatchingSeries(s, allseries) {
var res = null
for (var i = 0; i < allseries.length; ++i) {
if (s == allseries[i])
break;
if (allseries[i].stack == s.stack)
res = allseries[i];
}
return res;
}
function stackData(plot, s, datapoints) {
if (s.stack == null)
return;
var other = findMatchingSeries(s, plot.getData());
if (!other)
return;
var ps = datapoints.pointsize,
points = datapoints.points,
otherps = other.datapoints.pointsize,
otherpoints = other.datapoints.points,
newpoints = [],
px, py, intery, qx, qy, bottom,
withlines = s.lines.show, withbars = s.bars.show,
withsteps = withlines && s.lines.steps,
i = 0, j = 0, l;
while (true) {
if (i >= points.length)
break;
l = newpoints.length;
if (j >= otherpoints.length
|| otherpoints[j] == null
|| points[i] == null) {
// degenerate cases
for (m = 0; m < ps; ++m)
newpoints.push(points[i + m]);
i += ps;
}
else {
// cases where we actually got two points
px = points[i];
py = points[i + 1];
qx = otherpoints[j];
qy = otherpoints[j + 1];
bottom = 0;
if (px == qx) {
for (m = 0; m < ps; ++m)
newpoints.push(points[i + m]);
newpoints[l + 1] += qy;
bottom = qy;
i += ps;
j += otherps;
}
else if (px > qx) {
// we got past point below, might need to
// insert interpolated extra point
if (withlines && i > 0 && points[i - ps] != null) {
intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
newpoints.push(qx);
newpoints.push(intery + qy)
for (m = 2; m < ps; ++m)
newpoints.push(points[i + m]);
bottom = qy;
}
j += otherps;
}
else {
for (m = 0; m < ps; ++m)
newpoints.push(points[i + m]);
// we might be able to interpolate a point below,
// this can give us a better y
if (withlines && j > 0 && otherpoints[j - ps] != null)
bottom = qy + (otherpoints[j - ps + 1] - qy) * (px - qx) / (otherpoints[j - ps] - qx);
newpoints[l + 1] += bottom;
i += ps;
}
if (l != newpoints.length && withbars)
newpoints[l + 2] += bottom;
}
// maintain the line steps invariant
if (withsteps && l != newpoints.length && l > 0
&& newpoints[l] != null
&& newpoints[l] != newpoints[l - ps]
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
for (m = 0; m < ps; ++m)
newpoints[l + ps + m] = newpoints[l + m];
newpoints[l + 1] = newpoints[l - ps + 1];
}
}
datapoints.points = newpoints;
}
plot.hooks.processDatapoints.push(stackData);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'stack',
version: '1.0'
});
})(jQuery);

1
website/flot/jquery.flot.stack.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(B){var A={series:{stack:null}};function C(F){function D(J,I){var H=null;for(var G=0;G<I.length;++G){if(J==I[G]){break}if(I[G].stack==J.stack){H=I[G]}}return H}function E(W,P,G){if(P.stack==null){return }var L=D(P,W.getData());if(!L){return }var T=G.pointsize,Y=G.points,H=L.datapoints.pointsize,S=L.datapoints.points,N=[],R,Q,I,a,Z,M,O=P.lines.show,K=P.bars.show,J=O&&P.lines.steps,X=0,V=0,U;while(true){if(X>=Y.length){break}U=N.length;if(V>=S.length||S[V]==null||Y[X]==null){for(m=0;m<T;++m){N.push(Y[X+m])}X+=T}else{R=Y[X];Q=Y[X+1];a=S[V];Z=S[V+1];M=0;if(R==a){for(m=0;m<T;++m){N.push(Y[X+m])}N[U+1]+=Z;M=Z;X+=T;V+=H}else{if(R>a){if(O&&X>0&&Y[X-T]!=null){I=Q+(Y[X-T+1]-Q)*(a-R)/(Y[X-T]-R);N.push(a);N.push(I+Z);for(m=2;m<T;++m){N.push(Y[X+m])}M=Z}V+=H}else{for(m=0;m<T;++m){N.push(Y[X+m])}if(O&&V>0&&S[V-T]!=null){M=Z+(S[V-T+1]-Z)*(R-a)/(S[V-T]-a)}N[U+1]+=M;X+=T}}if(U!=N.length&&K){N[U+2]+=M}}if(J&&U!=N.length&&U>0&&N[U]!=null&&N[U]!=N[U-T]&&N[U+1]!=N[U-T+1]){for(m=0;m<T;++m){N[U+T+m]=N[U+m]}N[U+1]=N[U-T+1]}}G.points=N}F.hooks.processDatapoints.push(E)}B.plot.plugins.push({init:C,options:A,name:"stack",version:"1.0"})})(jQuery);

Просмотреть файл

@ -0,0 +1,103 @@
/*
Flot plugin for thresholding data. Controlled through the option
"threshold" in either the global series options
series: {
threshold: {
below: number
color: colorspec
}
}
or in a specific series
$.plot($("#placeholder"), [{ data: [ ... ], threshold: { ... }}])
The data points below "below" are drawn with the specified color. This
makes it easy to mark points below 0, e.g. for budget data.
Internally, the plugin works by splitting the data into two series,
above and below the threshold. The extra series below the threshold
will have its label cleared and the special "originSeries" attribute
set to the original series. You may need to check for this in hover
events.
*/
(function ($) {
var options = {
series: { threshold: null } // or { below: number, color: color spec}
};
function init(plot) {
function thresholdData(plot, s, datapoints) {
if (!s.threshold)
return;
var ps = datapoints.pointsize, i, x, y, p, prevp,
thresholded = $.extend({}, s); // note: shallow copy
thresholded.datapoints = { points: [], pointsize: ps };
thresholded.label = null;
thresholded.color = s.threshold.color;
thresholded.threshold = null;
thresholded.originSeries = s;
thresholded.data = [];
var below = s.threshold.below,
origpoints = datapoints.points,
addCrossingPoints = s.lines.show;
threspoints = [];
newpoints = [];
for (i = 0; i < origpoints.length; i += ps) {
x = origpoints[i]
y = origpoints[i + 1];
prevp = p;
if (y < below)
p = threspoints;
else
p = newpoints;
if (addCrossingPoints && prevp != p && x != null
&& i > 0 && origpoints[i - ps] != null) {
var interx = (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]) * (below - y) + x;
prevp.push(interx);
prevp.push(below);
for (m = 2; m < ps; ++m)
prevp.push(origpoints[i + m]);
p.push(null); // start new segment
p.push(null);
for (m = 2; m < ps; ++m)
p.push(origpoints[i + m]);
p.push(interx);
p.push(below);
for (m = 2; m < ps; ++m)
p.push(origpoints[i + m]);
}
p.push(x);
p.push(y);
}
datapoints.points = newpoints;
thresholded.datapoints.points = threspoints;
if (thresholded.datapoints.points.length > 0)
plot.getData().push(thresholded);
// FIXME: there are probably some edge cases left in bars
}
plot.hooks.processDatapoints.push(thresholdData);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'threshold',
version: '1.0'
});
})(jQuery);

1
website/flot/jquery.flot.threshold.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(B){var A={series:{threshold:null}};function C(D){function E(L,S,M){if(!S.threshold){return }var F=M.pointsize,I,O,N,G,K,H=B.extend({},S);H.datapoints={points:[],pointsize:F};H.label=null;H.color=S.threshold.color;H.threshold=null;H.originSeries=S;H.data=[];var P=S.threshold.below,Q=M.points,R=S.lines.show;threspoints=[];newpoints=[];for(I=0;I<Q.length;I+=F){O=Q[I];N=Q[I+1];K=G;if(N<P){G=threspoints}else{G=newpoints}if(R&&K!=G&&O!=null&&I>0&&Q[I-F]!=null){var J=(O-Q[I-F])/(N-Q[I-F+1])*(P-N)+O;K.push(J);K.push(P);for(m=2;m<F;++m){K.push(Q[I+m])}G.push(null);G.push(null);for(m=2;m<F;++m){G.push(Q[I+m])}G.push(J);G.push(P);for(m=2;m<F;++m){G.push(Q[I+m])}}G.push(O);G.push(N)}M.points=newpoints;H.datapoints.points=threspoints;if(H.datapoints.points.length>0){L.getData().push(H)}}D.hooks.processDatapoints.push(E)}B.plot.plugins.push({init:C,options:A,name:"threshold",version:"1.0"})})(jQuery);

4376
website/flot/jquery.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

19
website/flot/jquery.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

110
website/index.php Normal file
Просмотреть файл

@ -0,0 +1,110 @@
<?php
date_default_timezone_set("UTC");
// vim: set ts=4 sw=4 tw=99 et:
require_once("internals.php");
require_once("context.php");
init_database();
$smarty = new_smarty();
$cx = new Context();
$view = isset($_GET['view']) ? $_GET['view'] : 'normal';
if ($cx->view == 'breakdown') {
$graphs = makeIndividualGraphs($cx, array(1, 3, 4));
$tpl = "takethree-individual";
} else {
$graphs = makeTotalGraphs($cx, array(1, 3, 4));
$tpl = "takethree";
}
$machines = array(array('id' => 9,
'info' => 'Mac OS X, 32-bit (Mac Mini)'),
array('id' => 8,
'info' => 'Mac OS X, 64-bit (Mac Mini)'),
array('id' => 10,
'info' => 'Linux ARMv7 (nVidia Tegra 250)'));
$smarty->assign('machines', $machines);
$smarty->assign('machine_id', $cx->machine_id);
$smarty->assign('url_machine', $cx->url(array('machine' => false)));
$views = array(array('id' => 'overall',
'name' => 'Overall'),
array('id' => 'regress',
'name' => 'Regression Testing'),
array('id' => 'breakdown',
'name' => 'Test Breakdown'));
$smarty->assign('views', $views);
$smarty->assign('view', $cx->view);
$smarty->assign('url_view', $cx->url(array('view' => false)));
$smarty->assign('cx', $cx);
$smarty->assign('graphs', $graphs);
$smarty->display("$tpl.tpl");
function makeIndividualGraphs(&$cx, $list)
{
$graphs = array();
for ($i = 0; $i < count($list); $i++) {
$suite_id = $list[$i];
$query = "SELECT name, description, better_direction
FROM awfy_suite
WHERE id = $suite_id";
$result = awfy_query($query);
if (!mysql_num_rows($result))
continue;
$row = mysql_fetch_assoc($result);
$suite_name = $row['name'];
$suite_desc = $row['description'];
$suite_direction = $row['better_direction'];
$filter = RunFilter::FromGET($cx, $suite_id);
$query = "SELECT test
FROM awfy_breakdown b
WHERE run_id IN (" . $filter->idstr . ")
AND suite_id = $suite_id
GROUP BY test";
$result = awfy_query($query);
while (($row = mysql_fetch_assoc($result)) !== FALSE) {
$test_name = $row['test'];
$gb = new GraphBuilder($cx, $filter, $test_name);
$graphs[$suite_name . "-" . $test_name] = array(
'description' => $suite_name . "-" . $test_name,
'direction' => $suite_direction,
'graph' => $gb
);
}
}
return $graphs;
}
function makeTotalGraphs(&$cx, $list)
{
$graphs = array();
for ($i = 0; $i < count($list); $i++) {
$id = $list[$i];
$query = "SELECT name, description, better_direction
FROM awfy_suite
WHERE id = $id";
$result = awfy_query($query);
if (!mysql_num_rows($result))
continue;
$row = mysql_fetch_assoc($result);
$filter = RunFilter::FromGET($cx, $id);
$gb = new GraphBuilder($cx, $filter);
$graphs[$row['name']] = array(
'description' => $row['description'],
'direction' => $row['better_direction'],
'graph' => $gb
);
}
return $graphs;
}

75
website/internals.php Executable file
Просмотреть файл

@ -0,0 +1,75 @@
<?php
// vim: set ts=4 sw=4 tw=99 et:
require_once("smarty/libs/Smarty.class.php");
function init_database()
{
mysql_connect("localhost", "***", "***") or die("ERROR: " . mysql_error());
mysql_select_db("dvander") or die("ERROR: " . mysql_error());
}
function GET_int($name)
{
if (isset($_GET[$name]))
return intval($_GET[$name]);
return 0;
}
function GET_string($name)
{
if (isset($_GET[$name]))
return $_GET[$name];
return "";
}
function new_smarty()
{
$smarty = new Smarty;
$base = '/usr/apache/htdocs';
$smarty->template_dir = $base . '/templates';
$smarty->compile_dir = $base . '/cache_templates';
$smarty->cache_dir = $base . '/cache_stuff';
return $smarty;
}
function find_vendor_of_mode_id($mode_id)
{
$query = "SELECT vendor_id FROM awfy_mode
WHERE id = $mode_id";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1)
return 01;
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function find_mode($mode)
{
$query = "SELECT id FROM awfy_mode
WHERE mode = '" . mysql_real_escape_string($mode) . "'";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1)
return -1;
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function find_suite($suite)
{
$query = "SELECT id FROM awfy_suite
WHERE name = '" . mysql_real_escape_string($suite) . "'";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1)
return -1;
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function awfy_query($query)
{
$result = mysql_query($query) or die(mysql_error());
return $result;
}
?>

77
website/navbar.css Normal file
Просмотреть файл

@ -0,0 +1,77 @@
/* vim: set ts=4 sw=4 tw=99 et: */
#navbar
{
margin: 0;
display: inline;
}
#navbar li
{
line-height: 20px;
}
#navbar > li
{
/* float: left; */
list-style: none;
margin-bottom: 1em;
border: 1px solid transparent;
text-align: right;
width: 70px;
padding-right: 5px;
}
#navbar li a
{
display: block;
margin: 0 10px;
text-decoration: none;
width: 70px;
color: #000000;
white-space: nowrap;
}
#navbar li.active
{
background: #F2F2F2;
cursor: pointer;
}
#navbar li.active ul
{
visibility: visible;
}
#navbar li ul
{
border-right: 1px outset black;
border-bottom: 1px outset black;
margin-top: -21px; // == line-height + border height
margin-left: 75px; // == parent width + parent padding
padding: 0;
position: absolute;
visibility: hidden;
background: #F2F2F2;
z-index: 0;
}
#navbar li ul li
{
float: none;
display: inline;
text-align: left;
margin: 0;
padding: 0;
}
#navbar li ul li a
{
width: auto;
}
#navbar li ul li a:hover
{
text-decoration:underline;
}

33
website/navbar.js Normal file
Просмотреть файл

@ -0,0 +1,33 @@
/* vim: set ts=4 sw=4 tw=99 et: */
function NavBar(name)
{
var timeout = 200;
var closeTimer = null;
function open() {
cancel();
close();
$(this).addClass('active');
}
function close() {
$('#' + name + ' > li').removeClass('active'); // make sure all others are closed
}
function timer() {
closeTimer = window.setTimeout(close, timeout);
}
function cancel() {
if (closeTimer) {
window.clearTimeout(closeTimer);
closeTimer = null;
}
}
$('#' + name + ' > li').bind('mouseover', open);
$('#' + name + ' > li').bind('mouseout', timer);
$('#' + name + ' > li').bind('onclick', open);
document.onclick = close;
}

5
website/readme.txt Normal file
Просмотреть файл

@ -0,0 +1,5 @@
internals.php has settings redacted - fill 'em in, under mysql_connect and /usr/apache/htdocs
UPDATED.PHP should be renamed to something random, not very secure i know but this is a hack job.
flot is modified, see http://code.google.com/p/flot/issues/detail?id=23 comment #25's patch

182
website/schema.sql Normal file
Просмотреть файл

@ -0,0 +1,182 @@
-- phpMyAdmin SQL Dump
-- version 3.3.9
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Feb 03, 2011 at 12:53 AM
-- Server version: 5.1.41
-- PHP Version: 5.3.5
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- Database: `dvander`
--
-- --------------------------------------------------------
--
-- Table structure for table `awfy_breakdown`
--
CREATE TABLE IF NOT EXISTS `awfy_breakdown` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`run_id` int(11) DEFAULT NULL,
`suite_id` int(11) DEFAULT NULL,
`mode_id` int(11) DEFAULT NULL,
`test` varchar(45) DEFAULT NULL,
`score` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `run_id` (`run_id`),
KEY `suite_id` (`suite_id`),
KEY `mode_id` (`mode_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=329903 ;
-- --------------------------------------------------------
--
-- Table structure for table `awfy_build`
--
CREATE TABLE IF NOT EXISTS `awfy_build` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`run_id` int(10) unsigned NOT NULL,
`mode_id` int(10) unsigned NOT NULL,
`cset` varchar(256) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index2` (`run_id`,`mode_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=12680 ;
-- --------------------------------------------------------
--
-- Table structure for table `awfy_score`
--
CREATE TABLE IF NOT EXISTS `awfy_score` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`run_id` int(11) DEFAULT NULL,
`suite_id` int(11) DEFAULT NULL,
`mode_id` int(11) DEFAULT NULL,
`score` double DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `run_id` (`run_id`),
KEY `mode_id` (`mode_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=24486 ;
-- --------------------------------------------------------
--
-- Table structure for table `fast_run`
--
CREATE TABLE IF NOT EXISTS `fast_run` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cpu` varchar(20) NOT NULL,
`os` varchar(20) NOT NULL,
`machine` int(10) unsigned NOT NULL,
`stamp` int(10) unsigned NOT NULL,
`cset` varchar(160) NOT NULL,
`status` int(11) NOT NULL,
`error` mediumtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3502 ;
-- phpMyAdmin SQL Dump
-- version 3.3.9
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Feb 03, 2011 at 12:53 AM
-- Server version: 5.1.41
-- PHP Version: 5.3.5
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- Database: `dvander`
--
-- --------------------------------------------------------
--
-- Table structure for table `awfy_mode`
--
CREATE TABLE IF NOT EXISTS `awfy_mode` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`vendor_id` int(10) unsigned NOT NULL,
`mode` varchar(12) NOT NULL,
`name` varchar(255) NOT NULL,
`color` varchar(45) DEFAULT NULL,
`level` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `mode` (`mode`),
UNIQUE KEY `index3` (`vendor_id`,`mode`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;
--
-- Dumping data for table `awfy_mode`
--
INSERT INTO `awfy_mode` (`id`, `vendor_id`, `mode`, `name`, `color`, `level`) VALUES
(1, 2, 'moom', 'JM', '#000000', 10),
(2, 2, 'mooj', 'TM+JM', '#6f0a93', 1),
(3, 1, 'v8', 'v8', '#4DA74D', 1),
(4, 3, 'jsc', 'jsc', '#cf4b4b', 1),
(5, 3, 'jsci', 'no JIT', '#ef8b8b', 10),
(6, 2, 'j', 'TM', '#ffa451', 10),
(7, 2, 'm', 'JM', '#000000', 10),
(8, 2, 'i', 'no JIT', '#bbbbbb', 10),
(9, 2, 'mj', 'TM+JM', '#6f0a93', 10),
(11, 2, 'tm', '', '', 10);
-- --------------------------------------------------------
--
-- Table structure for table `awfy_suite`
--
CREATE TABLE IF NOT EXISTS `awfy_suite` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`description` varchar(45) DEFAULT NULL,
`better_direction` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
--
-- Dumping data for table `awfy_suite`
--
INSERT INTO `awfy_suite` (`id`, `name`, `description`, `better_direction`) VALUES
(1, 'ss', 'SunSpider', -1),
(2, 'v8', 'V8 (SS harness)', -1),
(3, 'v8real', 'V8 Benchmark', 1),
(4, 'kraken', 'Kraken', -1);
-- --------------------------------------------------------
--
-- Table structure for table `awfy_vendor`
--
CREATE TABLE IF NOT EXISTS `awfy_vendor` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`vendor` varchar(30) NOT NULL,
`csetURL` varchar(255) NOT NULL,
`browser` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
--
-- Dumping data for table `awfy_vendor`
--
INSERT INTO `awfy_vendor` (`id`, `name`, `vendor`, `csetURL`, `browser`) VALUES
(1, 'V8', 'Google', 'http://code.google.com/p/v8/source/detail?r=', 'Chrome'),
(2, 'SpiderMonkey', 'Mozilla', 'http://hg.mozilla.org/tracemonkey/rev/', 'Firefox'),
(3, 'Nitro', 'Apple', 'http://trac.webkit.org/changeset/', 'Safari');

165
website/smarty/COPYING.lib Normal file
Просмотреть файл

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

570
website/smarty/README Normal file
Просмотреть файл

@ -0,0 +1,570 @@
Smarty 3.0.5
Author: Monte Ohrt <monte at ohrt dot com >
Author: Uwe Tews
AN INTRODUCTION TO SMARTY 3
NOTICE for 3.0.5 release:
Smarty now follows the PHP error_reporting level by default. If PHP does not mask E_NOTICE and you try to access an unset template variable, you will now get an E_NOTICE warning. To revert to the old behavior:
$smarty->error_reporting = E_ALL & ~E_NOTICE;
NOTICE for 3.0 release:
IMPORTANT: Some API adjustments have been made between the RC4 and 3.0 release.
We felt it is better to make these now instead of after a 3.0 release, then have to
immediately deprecate APIs in 3.1. Online documentation has been updated
to reflect these changes. Specifically:
---- API CHANGES RC4 -> 3.0 ----
$smarty->register->*
$smarty->unregister->*
$smarty->utility->*
$samrty->cache->*
Have all been changed to local method calls such as:
$smarty->clearAllCache()
$smarty->registerFoo()
$smarty->unregisterFoo()
$smarty->testInstall()
etc.
Registration of function, block, compiler, and modifier plugins have been
consolidated under two API calls:
$smarty->registerPlugin(...)
$smarty->unregisterPlugin(...)
Registration of pre, post, output and variable filters have been
consolidated under two API calls:
$smarty->registerFilter(...)
$smarty->unregisterFilter(...)
Please refer to the online documentation for all specific changes:
http://www.smarty.net/documentation
----
The Smarty 3 API has been refactored to a syntax geared
for consistency and modularity. The Smarty 2 API syntax is still supported, but
will throw a deprecation notice. You can disable the notices, but it is highly
recommended to adjust your syntax to Smarty 3, as the Smarty 2 syntax must run
through an extra rerouting wrapper.
Basically, all Smarty methods now follow the "fooBarBaz" camel case syntax. Also,
all Smarty properties now have getters and setters. So for example, the property
$smarty->cache_dir can be set with $smarty->setCacheDir('foo/') and can be
retrieved with $smarty->getCacheDir().
Some of the Smarty 3 APIs have been revoked such as the "is*" methods that were
just duplicate functions of the now available "get*" methods.
Here is a rundown of the Smarty 3 API:
$smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->display($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->isCached($template, $cache_id = null, $compile_id = null)
$smarty->createData($parent = null)
$smarty->createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->enableSecurity()
$smarty->disableSecurity()
$smarty->setTemplateDir($template_dir)
$smarty->addTemplateDir($template_dir)
$smarty->templateExists($resource_name)
$smarty->loadPlugin($plugin_name, $check = true)
$smarty->loadFilter($type, $name)
$smarty->setExceptionHandler($handler)
$smarty->addPluginsDir($plugins_dir)
$smarty->getGlobal($varname = null)
$smarty->getRegisteredObject($name)
$smarty->getDebugTemplate()
$smarty->setDebugTemplate($tpl_name)
$smarty->assign($tpl_var, $value = null, $nocache = false)
$smarty->assignGlobal($varname, $value = null, $nocache = false)
$smarty->assignByRef($tpl_var, &$value, $nocache = false)
$smarty->append($tpl_var, $value = null, $merge = false, $nocache = false)
$smarty->appendByRef($tpl_var, &$value, $merge = false)
$smarty->clearAssign($tpl_var)
$smarty->clearAllAssign()
$smarty->configLoad($config_file, $sections = null)
$smarty->getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true)
$smarty->getConfigVariable($variable)
$smarty->getStreamVariable($variable)
$smarty->getConfigVars($varname = null)
$smarty->clearConfig($varname = null)
$smarty->getTemplateVars($varname = null, $_ptr = null, $search_parents = true)
$smarty->clearAllCache($exp_time = null, $type = null)
$smarty->clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
$smarty->registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = array())
$smarty->registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
$smarty->registerFilter($type, $function_name)
$smarty->registerResource($resource_type, $function_names)
$smarty->registerDefaultPluginHandler($function_name)
$smarty->registerDefaultTemplateHandler($function_name)
$smarty->unregisterPlugin($type, $tag)
$smarty->unregisterObject($object_name)
$smarty->unregisterFilter($type, $function_name)
$smarty->unregisterResource($resource_type)
$smarty->compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
$smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
$smarty->testInstall()
// then all the getters/setters, available for all properties. Here are a few:
$caching = $smarty->getCaching(); // get $smarty->caching
$smarty->setCaching(true); // set $smarty->caching
$smarty->setDeprecationNotices(false); // set $smarty->deprecation_notices
$smarty->setCacheId($id); // set $smarty->cache_id
$debugging = $smarty->getDebugging(); // get $smarty->debugging
FILE STRUCTURE
The Smarty 3 file structure is similar to Smarty 2:
/libs/
Smarty.class.php
/libs/sysplugins/
internal.*
/libs/plugins/
function.mailto.php
modifier.escape.php
...
A lot of Smarty 3 core functionality lies in the sysplugins directory; you do
not need to change any files here. The /libs/plugins/ folder is where Smarty
plugins are located. You can add your own here, or create a separate plugin
directory, just the same as Smarty 2. You will still need to create your own
/cache/, /templates/, /templates_c/, /configs/ folders. Be sure /cache/ and
/templates_c/ are writable.
The typical way to use Smarty 3 should also look familiar:
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->assign('foo','bar');
$smarty->display('index.tpl');
However, Smarty 3 works completely different on the inside. Smarty 3 is mostly
backward compatible with Smarty 2, except for the following items:
*) Smarty 3 is PHP 5 only. It will not work with PHP 4.
*) The {php} tag is disabled by default. Enable with $smarty->allow_php_tag=true.
*) Delimiters surrounded by whitespace are no longer treated as Smarty tags.
Therefore, { foo } will not compile as a tag, you must use {foo}. This change
Makes Javascript/CSS easier to work with, eliminating the need for {literal}.
This can be disabled by setting $smarty->auto_literal = false;
*) The Smarty 3 API is a bit different. Many Smarty 2 API calls are deprecated
but still work. You will want to update your calls to Smarty 3 for maximum
efficiency.
There are many things that are new to Smarty 3. Here are the notable items:
LEXER/PARSER
============
Smarty 3 now uses a lexing tokenizer for its parser/compiler. Basically, this
means Smarty has some syntax additions that make life easier such as in-template
math, shorter/intuitive function parameter options, infinite function recursion,
more accurate error handling, etc.
WHAT IS NEW IN SMARTY TEMPLATE SYNTAX
=====================================
Smarty 3 allows expressions almost anywhere. Expressions can include PHP
functions as long as they are not disabled by the security policy, object
methods and properties, etc. The {math} plugin is no longer necessary but
is still supported for BC.
Examples:
{$x+$y} will output the sum of x and y.
{$foo = strlen($bar)} function in assignment
{assign var=foo value= $x+$y} in attributes
{$foo = myfunct( ($x+$y)*3 )} as function parameter
{$foo[$x+3]} as array index
Smarty tags can be used as values within other tags.
Example: {$foo={counter}+3}
Smarty tags can also be used inside double quoted strings.
Example: {$foo="this is message {counter}"}
You can define arrays within templates.
Examples:
{assign var=foo value=[1,2,3]}
{assign var=foo value=['y'=>'yellow','b'=>'blue']}
Arrays can be nested.
{assign var=foo value=[1,[9,8],3]}
There is a new short syntax supported for assigning variables.
Example: {$foo=$bar+2}
You can assign a value to a specific array element. If the variable exists but
is not an array, it is converted to an array before the new values are assigned.
Examples:
{$foo['bar']=1}
{$foo['bar']['blar']=1}
You can append values to an array. If the variable exists but is not an array,
it is converted to an array before the new values are assigned.
Example: {$foo[]=1}
You can use a PHP-like syntax for accessing array elements, as well as the
original "dot" notation.
Examples:
{$foo[1]} normal access
{$foo['bar']}
{$foo['bar'][1]}
{$foo[$x+$x]} index may contain any expression
{$foo[$bar[1]]} nested index
{$foo[section_name]} smarty section access, not array access!
The original "dot" notation stays, and with improvements.
Examples:
{$foo.a.b.c} => $foo['a']['b']['c']
{$foo.a.$b.c} => $foo['a'][$b]['c'] with variable index
{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] with expression as index
{$foo.a.{$b.c}} => $foo['a'][$b['c']] with nested index
note that { and } are used to address ambiguties when nesting the dot syntax.
Variable names themselves can be variable and contain expressions.
Examples:
$foo normal variable
$foo_{$bar} variable name containing other variable
$foo_{$x+$y} variable name containing expressions
$foo_{$bar}_buh_{$blar} variable name with multiple segments
{$foo_{$x}} will output the variable $foo_1 if $x has a value of 1.
Object method chaining is implemented.
Example: {$object->method1($x)->method2($y)}
{for} tag added for looping (replacement for {section} tag):
{for $x=0, $y=count($foo); $x<$y; $x++} .... {/for}
Any number of statements can be used separated by comma as the first
inital expression at {for}.
{for $x = $start to $end step $step} ... {/for}is in the SVN now .
You can use also
{for $x = $start to $end} ... {/for}
In this case the step value will be automaticall 1 or -1 depending on the start and end values.
Instead of $start and $end you can use any valid expression.
Inside the loop the following special vars can be accessed:
$x@iteration = number of iteration
$x@total = total number of iterations
$x@first = true on first iteration
$x@last = true on last iteration
The Smarty 2 {section} syntax is still supported.
New shorter {foreach} syntax to loop over an array.
Example: {foreach $myarray as $var}...{/foreach}
Within the foreach loop, properties are access via:
$var@key foreach $var array key
$var@iteration foreach current iteration count (1,2,3...)
$var@index foreach current index count (0,1,2...)
$var@total foreach $var array total
$var@first true on first iteration
$var@last true on last iteration
The Smarty 2 {foreach} tag syntax is still supported.
NOTE: {$bar[foo]} still indicates a variable inside of a {section} named foo.
If you want to access an array element with index foo, you must use quotes
such as {$bar['foo']}, or use the dot syntax {$bar.foo}.
while block tag is now implemented:
{while $foo}...{/while}
{while $x lt 10}...{/while}
Direct access to PHP functions:
Just as you can use PHP functions as modifiers directly, you can now access
PHP functions directly, provided they are permitted by security settings:
{time()}
There is a new {function}...{/function} block tag to implement a template function.
This enables reuse of code sequences like a plugin function. It can call itself recursively.
Template function must be called with the new {call name=foo...} tag.
Example:
Template file:
{function name=menu level=0}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{call name=menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{call name=menu data=$menu}
Generated output:
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
The function tag itself must have the "name" attribute. This name is the tag
name when calling the function. The function tag may have any number of
additional attributes. These will be default settings for local variables.
New {nocache} block function:
{nocache}...{/nocache} will declare a section of the template to be non-cached
when template caching is enabled.
New nocache attribute:
You can declare variable/function output as non-cached with the nocache attribute.
Examples:
{$foo nocache=true}
{$foo nocache} /* same */
{foo bar="baz" nocache=true}
{foo bar="baz" nocache} /* same */
{time() nocache=true}
{time() nocache} /* same */
Or you can also assign the variable in your script as nocache:
$smarty->assign('foo',$something,true); // third param is nocache setting
{$foo} /* non-cached */
$smarty.current_dir returns the directory name of the current template.
You can use strings directly as templates with the "string" resource type.
Examples:
$smarty->display('string:This is my template, {$foo}!'); // php
{include file="string:This is my template, {$foo}!"} // template
VARIABLE SCOPE / VARIABLE STORAGE
=================================
In Smarty 2, all assigned variables were stored within the Smarty object.
Therefore, all variables assigned in PHP were accessible by all subsequent
fetch and display template calls.
In Smarty 3, we have the choice to assign variables to the main Smarty object,
to user-created data objects, and to user-created template objects.
These objects can be chained. The object at the end of a chain can access all
variables belonging to that template and all variables within the parent objects.
The Smarty object can only be the root of a chain, but a chain can be isolated
from the Smarty object.
All known Smarty assignment interfaces will work on the data and template objects.
Besides the above mentioned objects, there is also a special storage area for
global variables.
A Smarty data object can be created as follows:
$data = $smarty->createData(); // create root data object
$data->assign('foo','bar'); // assign variables as usual
$data->config_load('my.conf'); // load config file
$data= $smarty->createData($smarty); // create data object having a parent link to
the Smarty object
$data2= $smarty->createData($data); // create data object having a parent link to
the $data data object
A template object can be created by using the createTemplate method. It has the
same parameter assignments as the fetch() or display() method.
Function definition:
function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
The first parameter can be a template name, a smarty object or a data object.
Examples:
$tpl = $smarty->createTemplate('mytpl.tpl'); // create template object not linked to any parent
$tpl->assign('foo','bar'); // directly assign variables
$tpl->config_load('my.conf'); // load config file
$tpl = $smarty->createTemplate('mytpl.tpl',$smarty); // create template having a parent link to the Smarty object
$tpl = $smarty->createTemplate('mytpl.tpl',$data); // create template having a parent link to the $data object
The standard fetch() and display() methods will implicitly create a template object.
If the $parent parameter is not specified in these method calls, the template object
is will link back to the Smarty object as it's parent.
If a template is called by an {include...} tag from another template, the
subtemplate links back to the calling template as it's parent.
All variables assigned locally or from a parent template are accessible. If the
template creates or modifies a variable by using the {assign var=foo...} or
{$foo=...} tags, these new values are only known locally (local scope). When the
template exits, none of the new variables or modifications can be seen in the
parent template(s). This is same behavior as in Smarty 2.
With Smarty 3, we can assign variables with a scope attribute which allows the
availablility of these new variables or modifications globally (ie in the parent
templates.)
Possible scopes are local, parent, root and global.
Examples:
{assign var=foo value='bar'} // no scope is specified, the default 'local'
{$foo='bar'} // same, local scope
{assign var=foo value='bar' scope='local'} // same, local scope
{assign var=foo value='bar' scope='parent'} // Values will be available to the parent object
{$foo='bar' scope='parent'} // (normally the calling template)
{assign var=foo value='bar' scope='root'} // Values will be exported up to the root object, so they can
{$foo='bar' scope='root'} // be seen from all templates using the same root.
{assign var=foo value='bar' scope='global'} // Values will be exported to global variable storage,
{$foo='bar' scope='global'} // they are available to any and all templates.
The scope attribute can also be attached to the {include...} tag. In this case,
the specified scope will be the default scope for all assignments within the
included template.
PLUGINS
=======
Smarty3 are following the same coding rules as in Smarty2.
The only difference is that the template object is passed as additional third parameter.
smarty_plugintype_name (array $params, object $smarty, object $template)
The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty2 internals.
TEMPLATE INHERITANCE:
=====================
With template inheritance you can define blocks, which are areas that can be
overriden by child templates, so your templates could look like this:
parent.tpl:
<html>
<head>
<title>{block name='title'}My site name{/block}</title>
</head>
<body>
<h1>{block name='page-title'}Default page title{/block}</h1>
<div id="content">
{block name='content'}
Default content
{/block}
</div>
</body>
</html>
child.tpl:
{extends file='parent.tpl'}
{block name='title'}
Child title
{/block}
grandchild.tpl:
{extends file='child.tpl'}
{block name='title'}Home - {$smarty.block.parent}{/block}
{block name='page-title'}My home{/block}
{block name='content'}
{foreach $images as $img}
<img src="{$img.url}" alt="{$img.description}" />
{/foreach}
{/block}
We redefined all the blocks here, however in the title block we used {$smarty.block.parent},
which tells Smarty to insert the default content from the parent template in its place.
The content block was overriden to display the image files, and page-title has also be
overriden to display a completely different title.
If we render grandchild.tpl we will get this:
<html>
<head>
<title>Home - Child title</title>
</head>
<body>
<h1>My home</h1>
<div id="content">
<img src="/example.jpg" alt="image" />
<img src="/example2.jpg" alt="image" />
<img src="/example3.jpg" alt="image" />
</div>
</body>
</html>
NOTE: In the child templates everything outside the {extends} or {block} tag sections
is ignored.
The inheritance tree can be as big as you want (meaning you can extend a file that
extends another one that extends another one and so on..), but be aware that all files
have to be checked for modifications at runtime so the more inheritance the more overhead you add.
Instead of defining the parent/child relationships with the {extends} tag in the child template you
can use the resource as follow:
$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl');
Child {block} tags may optionally have a append or prepend attribute. In this case the parent block content
is appended or prepended to the child block content.
{block name='title' append} My title {/block}
PHP STREAMS:
============
(see online documentation)
VARIBLE FILTERS:
================
(see online documentation)
STATIC CLASS ACCESS AND NAMESPACE SUPPORT
=========================================
You can register a class with optional namespace for the use in the template like:
$smarty->register->templateClass('foo','name\name2\myclass');
In the template you can use it like this:
{foo::method()} etc.
=======================
Please look through it and send any questions/suggestions/etc to the forums.
http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168
Monte and Uwe

Просмотреть файл

@ -0,0 +1,109 @@
= Known incompatibilities with Smarty 2 =
== Syntax ==
Smarty 3 API has a new syntax. Much of the Smarty 2 syntax is supported
by a wrapper but deprecated. See the README that comes with Smarty 3 for more
information.
The {$array|@mod} syntax has always been a bit confusing, where an "@" is required
to apply a modifier to an array instead of the individual elements. Normally you
always want the modifier to apply to the variable regardless of its type. In Smarty 3,
{$array|mod} and {$array|@mod} behave identical. It is safe to drop the "@" and the
modifier will still apply to the array. If you really want the modifier to apply to
each array element, you must loop the array in-template, or use a custom modifier that
supports array iteration. Most smarty functions already escape values where necessary
such as {html_options}
== PHP Version ==
Smarty 3 is PHP 5 only. It will not work with PHP 4.
== {php} Tag ==
The {php} tag is disabled by default. The use of {php} tags is
deprecated. It can be enabled with $smarty->allow_php_tag=true.
But if you scatter PHP code which belongs together into several
{php} tags it may not work any longer.
== Delimiters and whitespace ==
Delimiters surrounded by whitespace are no longer treated as Smarty tags.
Therefore, { foo } will not compile as a tag, you must use {foo}. This change
Makes Javascript/CSS easier to work with, eliminating the need for {literal}.
This can be disabled by setting $smarty->auto_literal = false;
== Unquoted Strings ==
Smarty 2 was a bit more forgiving (and ambiguous) when it comes to unquoted strings
in parameters. Smarty3 is more restrictive. You can still pass strings without quotes
so long as they contain no special characters. (anything outside of A-Za-z0-9_)
For example filename strings must be quoted
<source lang="smarty">
{include file='path/foo.tpl'}
</source>
== Extending the Smarty class ==
Smarty 3 makes use of the __construct method for initialization. If you are extending
the Smarty class, its constructor is not called implicitly if the your child class defines
its own constructor. In order to run Smarty's constructor, a call to parent::__construct()
within your child constructor is required.
<source lang="php">
class MySmarty extends Smarty {
function __construct() {
parent::__construct();
// your initialization code goes here
}
}
</source>
== Autoloader ==
Smarty 3 does register its own autoloader with spl_autoload_register. If your code has
an existing __autoload function then this function must be explicitly registered on
the __autoload stack. See http://us3.php.net/manual/en/function.spl-autoload-register.php
for further details.
== Plugin Filenames ==
Smarty 3 optionally supports the PHP spl_autoloader. The autoloader requires filenames
to be lower case. Because of this, Smarty plugin file names must also be lowercase.
In Smarty 2, mixed case file names did work.
== Scope of Special Smarty Variables ==
In Smarty 2 the special Smarty variables $smarty.section... and $smarty.foreach...
had global scope. If you had loops with the same name in subtemplates you could accidentally
overwrite values of parent template.
In Smarty 3 these special Smarty variable have only local scope in the template which
is defining the loop. If you need their value in a subtemplate you have to pass them
as parameter.
<source lang="smarty">
{include file='path/foo.tpl' index=$smarty.section.foo.index}
</source>
== SMARTY_RESOURCE_CHAR_SET ==
Smarty 3 sets the constant SMARTY_RESOURCE_CHAR_SET to utf-8 as default template charset.
This is now used also on modifiers like escape as default charset. If your templates use
other charsets make sure that you define the constant accordingly. Otherwise you may not
get any output.
== newline at {if} tags ==
A \n was added to the compiled code of the {if},{else},{elseif},{/if} tags to get output of newlines as expected by the template source.
If one of the {if} tags is at the line end you will now get a newline in the HTML output.
== trigger_error() ==
The API function trigger_error() has been removed because it did just map to PHP trigger_error.
However it's still included in the Smarty2 API wrapper.
== Smarty constants ==
The constants
SMARTY_PHP_PASSTHRU
SMARTY_PHP_QUOTE
SMARTY_PHP_REMOVE
SMARTY_PHP_ALLOW
have been replaced with class constants
Smarty::PHP_PASSTHRU
Smarty::PHP_QUOTE
Smarty::PHP_REMOVE
Smarty::PHP_ALLOW

Просмотреть файл

@ -0,0 +1,807 @@
<?php
/**
* Project: Smarty: the PHP compiling template engine
* File: Smarty.class.php
* SVN: $Id: Smarty.class.php 3794 2010-11-15 22:54:59Z uwe.tews@googlemail.com $
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For questions, help, comments, discussion, etc., please join the
* Smarty mailing list. Send a blank e-mail to
* smarty-discussion-subscribe@googlegroups.com
*
* @link http://www.smarty.net/
* @copyright 2008 New Digital Group, Inc.
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews
* @package Smarty
* @version 3.0.5
*/
/**
* define shorthand directory separator constant
*/
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
/**
* set SMARTY_DIR to absolute path to Smarty library files.
* Sets SMARTY_DIR only if user application has not already defined it.
*/
if (!defined('SMARTY_DIR')) {
define('SMARTY_DIR', dirname(__FILE__) . DS);
}
/**
* set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
* Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
*/
if (!defined('SMARTY_SYSPLUGINS_DIR')) {
define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS);
}
if (!defined('SMARTY_PLUGINS_DIR')) {
define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS);
}
if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
define('SMARTY_RESOURCE_CHAR_SET', 'UTF-8');
}
if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
}
/**
* register the class autoloader
*/
if (!defined('SMARTY_SPL_AUTOLOAD')) {
define('SMARTY_SPL_AUTOLOAD', 0);
}
if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false) {
$registeredAutoLoadFunctions = spl_autoload_functions();
if (!isset($registeredAutoLoadFunctions['spl_autoload'])) {
spl_autoload_register();
}
} else {
spl_autoload_register('smartyAutoload');
}
/**
* This is the main Smarty class
*/
class Smarty extends Smarty_Internal_Data {
/**
* constant definitions
*/
// smarty version
const SMARTY_VERSION = 'Smarty-3.0.5';
//define variable scopes
const SCOPE_LOCAL = 0;
const SCOPE_PARENT = 1;
const SCOPE_ROOT = 2;
const SCOPE_GLOBAL = 3;
// define caching modes
const CACHING_OFF = 0;
const CACHING_LIFETIME_CURRENT = 1;
const CACHING_LIFETIME_SAVED = 2;
/** modes for handling of "<?php ... ?>" tags in templates. **/
const PHP_PASSTHRU = 0; //-> print tags as plain text
const PHP_QUOTE = 1; //-> escape tags as entities
const PHP_REMOVE = 2; //-> escape tags as entities
const PHP_ALLOW = 3; //-> escape tags as entities
// filter types
const FILTER_POST = 'post';
const FILTER_PRE = 'pre';
const FILTER_OUTPUT = 'output';
const FILTER_VARIABLE = 'variable';
// plugin types
const PLUGIN_FUNCTION = 'function';
const PLUGIN_BLOCK = 'block';
const PLUGIN_COMPILER = 'compiler';
const PLUGIN_MODIFIER = 'modifier';
/**
* static variables
*/
// assigned global tpl vars
static $global_tpl_vars = array();
/**
* variables
*/
// auto literal on delimiters with whitspace
public $auto_literal = true;
// display error on not assigned variables
public $error_unassigned = false;
// template directory
public $template_dir = null;
// default template handler
public $default_template_handler_func = null;
// compile directory
public $compile_dir = null;
// plugins directory
public $plugins_dir = null;
// cache directory
public $cache_dir = null;
// config directory
public $config_dir = null;
// force template compiling?
public $force_compile = false;
// check template for modifications?
public $compile_check = true;
// locking concurrent compiles
public $compile_locking = true;
// use sub dirs for compiled/cached files?
public $use_sub_dirs = false;
// compile_error?
public $compile_error = false;
// caching enabled
public $caching = false;
// merge compiled includes
public $merge_compiled_includes = false;
// cache lifetime
public $cache_lifetime = 3600;
// force cache file creation
public $force_cache = false;
// cache_id
public $cache_id = null;
// compile_id
public $compile_id = null;
// template delimiters
public $left_delimiter = "{";
public $right_delimiter = "}";
// security
public $security_class = 'Smarty_Security';
public $security_policy = null;
public $php_handling = self::PHP_PASSTHRU;
public $allow_php_tag = false;
public $allow_php_templates = false;
public $direct_access_security = true;
public $trusted_dir = array();
// debug mode
public $debugging = false;
public $debugging_ctrl = 'NONE';
public $smarty_debug_id = 'SMARTY_DEBUG';
public $debug_tpl = null;
// When set, smarty does uses this value as error_reporting-level.
public $error_reporting = null;
// config var settings
public $config_overwrite = true; //Controls whether variables with the same name overwrite each other.
public $config_booleanize = true; //Controls whether config values of on/true/yes and off/false/no get converted to boolean
public $config_read_hidden = true; //Controls whether hidden config sections/vars are read from the file.
// config vars
public $config_vars = array();
// assigned tpl vars
public $tpl_vars = array();
// dummy parent object
public $parent = null;
// global template functions
public $template_functions = array();
// resource type used if none given
public $default_resource_type = 'file';
// caching type
public $caching_type = 'file';
// internal cache resource types
public $cache_resource_types = array('file');
// internal config properties
public $properties = array();
// config type
public $default_config_type = 'file';
// cached template objects
public $template_objects = null;
// check If-Modified-Since headers
public $cache_modified_check = false;
// registered plugins
public $registered_plugins = array();
// plugin search order
public $plugin_search_order = array('function', 'block', 'compiler', 'class');
// registered objects
public $registered_objects = array();
// registered classes
public $registered_classes = array();
// registered filters
public $registered_filters = array();
// registered resources
public $registered_resources = array();
// autoload filter
public $autoload_filters = array();
// status of filter on variable output
public $variable_filter = true;
// default modifier
public $default_modifiers = array();
// global internal smarty vars
static $_smarty_vars = array();
// start time for execution time calculation
public $start_time = 0;
// default file permissions
public $_file_perms = 0644;
// default dir permissions
public $_dir_perms = 0771;
// block tag hierarchy
public $_tag_stack = array();
// flag if {block} tag is compiled for template inheritance
public $inheritance = false;
// generate deprecated function call notices?
public $deprecation_notices = true;
// Smarty 2 BC
public $_version = self::SMARTY_VERSION;
/**
* Class constructor, initializes basic smarty properties
*/
public function __construct()
{
// selfpointer need by some other class methods
$this->smarty = $this;
if (is_callable('mb_internal_encoding')) {
mb_internal_encoding(SMARTY_RESOURCE_CHAR_SET);
}
$this->start_time = microtime(true);
// set default dirs
$this->template_dir = array('.' . DS . 'templates' . DS);
$this->compile_dir = '.' . DS . 'templates_c' . DS;
$this->plugins_dir = array(SMARTY_PLUGINS_DIR);
$this->cache_dir = '.' . DS . 'cache' . DS;
$this->config_dir = '.' . DS . 'configs' . DS;
$this->debug_tpl = SMARTY_DIR . 'debug.tpl';
if (!$this->debugging && $this->debugging_ctrl == 'URL') {
if (isset($_SERVER['QUERY_STRING'])) {
$_query_string = $_SERVER['QUERY_STRING'];
} else {
$_query_string = '';
}
if (false !== strpos($_query_string, $this->smarty_debug_id)) {
if (false !== strpos($_query_string, $this->smarty_debug_id . '=on')) {
// enable debugging for this browser session
setcookie('SMARTY_DEBUG', true);
$this->debugging = true;
} elseif (false !== strpos($_query_string, $this->smarty_debug_id . '=off')) {
// disable debugging for this browser session
setcookie('SMARTY_DEBUG', false);
$this->debugging = false;
} else {
// enable debugging for this page
$this->debugging = true;
}
} else {
if (isset($_COOKIE['SMARTY_DEBUG'])) {
$this->debugging = true;
}
}
}
if (isset($_SERVER['SCRIPT_NAME'])) {
$this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']);
}
}
/**
* Class destructor
*/
public function __destruct()
{
}
/**
* fetches a rendered Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $ |null $parent next higher level of Smarty variables
* @return string rendered template output
*/
public function fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false)
{
if (!empty($cache_id) && is_object($cache_id)) {
$parent = $cache_id;
$cache_id = null;
}
if ($parent === null) {
// get default Smarty data object
$parent = $this;
}
// create template object if necessary
($template instanceof $this->template_class)? $_template = $template :
$_template = $this->createTemplate ($template, $cache_id, $compile_id, $parent);
if (isset($this->error_reporting)) {
$_smarty_old_error_level = error_reporting($this->error_reporting);
}
// obtain data for cache modified check
if ($this->cache_modified_check && $this->caching && $display) {
$_isCached = $_template->isCached() && !$_template->has_nocache_code;
if ($_isCached) {
$_gmt_mtime = gmdate('D, d M Y H:i:s', $_template->getCachedTimestamp()) . ' GMT';
} else {
$_gmt_mtime = '';
}
}
// return redered template
if (isset($this->autoload_filters['output']) || isset($this->registered_filters['output'])) {
$_output = Smarty_Internal_Filter_Handler::runFilter('output', $_template->getRenderedTemplate(), $_template);
} else {
$_output = $_template->getRenderedTemplate();
}
$_template->rendered_content = null;
if (isset($this->error_reporting)) {
error_reporting($_smarty_old_error_level);
}
// display or fetch
if ($display) {
if ($this->caching && $this->cache_modified_check) {
$_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
if ($_isCached && $_gmt_mtime == $_last_modified_date) {
if (php_sapi_name() == 'cgi')
header('Status: 304 Not Modified');
else
header('HTTP/1.1 304 Not Modified');
} else {
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->getCachedTimestamp()) . ' GMT');
echo $_output;
}
} else {
echo $_output;
}
// debug output
if ($this->debugging) {
Smarty_Internal_Debug::display_debug($this);
}
return;
} else {
// return fetched content
return $_output;
}
}
/**
* displays a Smarty template
*
* @param string $ |object $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
*/
public function display($template, $cache_id = null, $compile_id = null, $parent = null)
{
// display template
$this->fetch ($template, $cache_id, $compile_id, $parent, true);
}
/**
* test if cache i valid
*
* @param string $ |object $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @return boolean cache status
*/
public function isCached($template, $cache_id = null, $compile_id = null, $parent = null)
{
if ($parent === null) {
$parent = $this;
}
if (!($template instanceof $this->template_class)) {
$template = $this->createTemplate ($template, $cache_id, $compile_id, $parent);
}
// return cache status of template
return $template->isCached();
}
/**
* creates a data object
*
* @param object $parent next higher level of Smarty variables
* @returns object data object
*/
public function createData($parent = null)
{
return new Smarty_Data($parent, $this);
}
/**
* creates a template object
*
* @param string $template the resource handle of the template file
* @param object $parent next higher level of Smarty variables
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @returns object template object
*/
public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
{
if (!empty($cache_id) && (is_object($cache_id) || is_array($cache_id))) {
$parent = $cache_id;
$cache_id = null;
}
if (!empty($parent) && is_array($parent)) {
$data = $parent;
$parent = null;
} else {
$data = null;
}
if (!is_object($template)) {
// we got a template resource
// already in template cache?
$_templateId = sha1($template . $cache_id . $compile_id);
if (isset($this->template_objects[$_templateId]) && $this->caching) {
// return cached template object
$tpl = $this->template_objects[$_templateId];
} else {
// create new template object
$tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id);
}
} else {
// just return a copy of template class
$tpl = $template;
}
// fill data if present
if (!empty($data) && is_array($data)) {
// set up variable values
foreach ($data as $_key => $_val) {
$tpl->tpl_vars[$_key] = new Smarty_variable($_val);
}
}
return $tpl;
}
/**
* Check if a template resource exists
*
* @param string $resource_name template name
* @return boolean status
*/
function templateExists($resource_name)
{
// create template object
$save = $this->template_objects;
$tpl = new $this->template_class($resource_name, $this);
// check if it does exists
$result = $tpl->isExisting();
$this->template_objects = $save;
return $result;
}
/**
* Returns a single or all global variables
*
* @param object $smarty
* @param string $varname variable name or null
* @return string variable value or or array of variables
*/
function getGlobal($varname = null)
{
if (isset($varname)) {
if (isset(self::$global_tpl_vars[$varname])) {
return self::$global_tpl_vars[$varname]->value;
} else {
return '';
}
} else {
$_result = array();
foreach (self::$global_tpl_vars AS $key => $var) {
$_result[$key] = $var->value;
}
return $_result;
}
}
/**
* Empty cache folder
*
* @param integer $exp_time expiration time
* @param string $type resource type
* @return integer number of cache files deleted
*/
function clearAllCache($exp_time = null, $type = null)
{
// load cache resource and call clearAll
return $this->loadCacheResource($type)->clearAll($exp_time);
}
/**
* Empty cache for a specific template
*
* @param string $template_name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param integer $exp_time expiration time
* @param string $type resource type
* @return integer number of cache files deleted
*/
function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
{
// load cache resource and call clear
return $this->loadCacheResource($type)->clear($template_name, $cache_id, $compile_id, $exp_time);
}
/**
* Loads security class and enables security
*/
public function enableSecurity($security_class = null)
{
if ($security_class instanceof Smarty_Security) {
$this->security_policy = $security_class;
return;
}
if ($security_class == null) {
$security_class = $this->security_class;
}
if (class_exists($security_class)) {
$this->security_policy = new $security_class($this);
} else {
throw new SmartyException("Security class '$security_class' is not defined");
}
}
/**
* Disable security
*/
public function disableSecurity()
{
$this->security_policy = null;
}
/**
* Loads cache resource.
*
* @param string $type cache resource type
* @return object of cache resource
*/
public function loadCacheResource($type = null) {
if (!isset($type)) {
$type = $this->caching_type;
}
if (in_array($type, $this->cache_resource_types)) {
$cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
return new $cache_resource_class($this);
}
else {
// try plugins dir
$cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type);
if ($this->loadPlugin($cache_resource_class)) {
return new $cache_resource_class($this);
}
else {
throw new SmartyException("Unable to load cache resource '{$type}'");
}
}
}
/**
* Set template directory
*
* @param string $ |array $template_dir folder(s) of template sorces
*/
public function setTemplateDir($template_dir)
{
$this->template_dir = (array)$template_dir;
return;
}
/**
* Adds template directory(s) to existing ones
*
* @param string $ |array $template_dir folder(s) of template sources
*/
public function addTemplateDir($template_dir)
{
$this->template_dir = array_unique(array_merge((array)$this->template_dir, (array)$template_dir));
return;
}
/**
* Adds directory of plugin files
*
* @param object $smarty
* @param string $ |array $ plugins folder
* @return
*/
function addPluginsDir($plugins_dir)
{
$this->plugins_dir = array_unique(array_merge((array)$this->plugins_dir, (array)$plugins_dir));
return;
}
/**
* return a reference to a registered object
*
* @param string $name object name
* @return object
*/
function getRegisteredObject($name)
{
if (!isset($this->registered_objects[$name]))
throw new SmartyException("'$name' is not a registered object");
if (!is_object($this->registered_objects[$name][0]))
throw new SmartyException("registered '$name' is not an object");
return $this->registered_objects[$name][0];
}
/**
* return name of debugging template
*
* @return string
*/
function getDebugTemplate()
{
return $this->debug_tpl;
}
/**
* set the debug template
*
* @param string $tpl_name
* @return bool
*/
function setDebugTemplate($tpl_name)
{
return $this->debug_tpl = $tpl_name;
}
/**
* Takes unknown classes and loads plugin files for them
* class name format: Smarty_PluginType_PluginName
* plugin filename format: plugintype.pluginname.php
*
* @param string $plugin_name class plugin name to load
* @return string |boolean filepath of loaded file or false
*/
public function loadPlugin($plugin_name, $check = true)
{
// if function or class exists, exit silently (already loaded)
if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false)))
return true;
// Plugin name is expected to be: Smarty_[Type]_[Name]
$_plugin_name = strtolower($plugin_name);
$_name_parts = explode('_', $_plugin_name, 3);
// class name must have three parts to be valid plugin
if (count($_name_parts) < 3 || $_name_parts[0] !== 'smarty') {
throw new SmartyException("plugin {$plugin_name} is not a valid name format");
return false;
}
// if type is "internal", get plugin from sysplugins
if ($_name_parts[1] == 'internal') {
$file = SMARTY_SYSPLUGINS_DIR . $_plugin_name . '.php';
if (file_exists($file)) {
require_once($file);
return $file;
} else {
return false;
}
}
// plugin filename is expected to be: [type].[name].php
$_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php";
// loop through plugin dirs and find the plugin
foreach((array)$this->plugins_dir as $_plugin_dir) {
if (strpos('/\\', substr($_plugin_dir, -1)) === false) {
$_plugin_dir .= DS;
}
$file = $_plugin_dir . $_plugin_filename;
if (file_exists($file)) {
require_once($file);
return $file;
}
}
// no plugin loaded
return false;
}
/**
* clean up properties on cloned object
*/
public function __clone()
{
// clear config vars
$this->config_vars = array();
// clear assigned tpl vars
$this->tpl_vars = array();
// clear objects for external methods
unset($this->register);
unset($this->filter);
}
/**
* Handle unknown class methods
*
* @param string $name unknown methode name
* @param array $args aurgument array
*/
public function __call($name, $args)
{
static $camel_func;
if (!isset($camel_func))
$camel_func = create_function('$c', 'return "_" . strtolower($c[1]);');
// see if this is a set/get for a property
$first3 = strtolower(substr($name, 0, 3));
if (in_array($first3, array('set', 'get')) && substr($name, 3, 1) !== '_') {
// try to keep case correct for future PHP 6.0 case-sensitive class methods
// lcfirst() not available < PHP 5.3.0, so improvise
$property_name = strtolower(substr($name, 3, 1)) . substr($name, 4);
// convert camel case to underscored name
$property_name = preg_replace_callback('/([A-Z])/', $camel_func, $property_name);
if (!property_exists($this, $property_name)) {
throw new SmartyException("property '$property_name' does not exist.");
return false;
}
if ($first3 == 'get')
return $this->$property_name;
else
return $this->$property_name = $args[0];
}
// Smarty Backward Compatible wrapper
if (strpos($name,'_') !== false) {
if (!isset($this->wrapper)) {
$this->wrapper = new Smarty_Internal_Wrapper($this);
}
return $this->wrapper->convert($name, $args);
}
// external Smarty methods ?
foreach(array('filter','register') as $external) {
if (method_exists("Smarty_Internal_{$external}",$name)) {
if (!isset($this->$external)) {
$class = "Smarty_Internal_{$external}";
$this->$external = new $class($this);
}
return call_user_func_array(array($this->$external,$name), $args);
}
}
if (in_array($name,array('clearCompiledTemplate','compileAllTemplates','compileAllConfig','testInstall','getTags'))) {
if (!isset($this->utility)) {
$this->utility = new Smarty_Internal_Utility($this);
}
return call_user_func_array(array($this->utility,$name), $args);
}
// PHP4 call to constructor?
if (strtolower($name) == 'smarty') {
throw new SmartyException('Please use parent::__construct() to call parent constuctor');
return false;
}
throw new SmartyException("Call of unknown function '$name'.");
}
}
/**
* Autoloader
*/
function smartyAutoload($class)
{
$_class = strtolower($class);
if (substr($_class, 0, 16) === 'smarty_internal_' || $_class == 'smarty_security') {
include SMARTY_SYSPLUGINS_DIR . $_class . '.php';
}
}
/**
* Smarty exception class
*/
Class SmartyException extends Exception {
}
/**
* Smarty compiler exception class
*/
Class SmartyCompilerException extends SmartyException {
}
?>

Просмотреть файл

@ -0,0 +1,136 @@
{capture name='_smarty_debug' assign=debug_output}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Smarty Debug Console</title>
<style type="text/css">
{literal}
body, h1, h2, td, th, p {
font-family: sans-serif;
font-weight: normal;
font-size: 0.9em;
margin: 1px;
padding: 0;
}
h1 {
margin: 0;
text-align: left;
padding: 2px;
background-color: #f0c040;
color: black;
font-weight: bold;
font-size: 1.2em;
}
h2 {
background-color: #9B410E;
color: white;
text-align: left;
font-weight: bold;
padding: 2px;
border-top: 1px solid black;
}
body {
background: black;
}
p, table, div {
background: #f0ead8;
}
p {
margin: 0;
font-style: italic;
text-align: center;
}
table {
width: 100%;
}
th, td {
font-family: monospace;
vertical-align: top;
text-align: left;
width: 50%;
}
td {
color: green;
}
.odd {
background-color: #eeeeee;
}
.even {
background-color: #fafafa;
}
.exectime {
font-size: 0.8em;
font-style: italic;
}
#table_assigned_vars th {
color: blue;
}
#table_config_vars th {
color: maroon;
}
{/literal}
</style>
</head>
<body>
<h1>Smarty Debug Console - Total Time {$execution_time|string_format:"%.5f"}</h1>
<h2>included templates &amp; config files (load time in seconds)</h2>
<div>
{foreach $template_data as $template}
<font color=brown>{$template.name}</font>
<span class="exectime">
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
</span>
<br>
{/foreach}
</div>
<h2>assigned template variables</h2>
<table id="table_assigned_vars">
{foreach $assigned_vars as $vars}
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
<th>${$vars@key|escape:'html'}</th>
<td>{$vars|debug_print_var}</td></tr>
{/foreach}
</table>
<h2>assigned config file variables (outer template scope)</h2>
<table id="table_config_vars">
{foreach $config_vars as $vars}
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
<th>{$vars@key|escape:'html'}</th>
<td>{$vars|debug_print_var}</td></tr>
{/foreach}
</table>
</body>
</html>
{/capture}
<script type="text/javascript">
{literal} if ( self.name == '' ) {
var title = 'Console';
}
else {
var title = 'Console_' + self.name;
}{/literal}
_smarty_console = window.open("",title.value,"width=680,height=600,resizable,scrollbars=yes");
_smarty_console.document.write("{$debug_output|escape:'javascript'}");
_smarty_console.document.close();
</script>

Просмотреть файл

@ -0,0 +1,27 @@
<?php
/**
* Smarty plugin to execute PHP code
*
* @package Smarty
* @subpackage PluginsBlock
* @author Uwe Tews
*/
/**
* Smarty {php}{/php} block plugin
*
* @param string $content contents of the block
* @param object $template template object
* @param boolean $ &$repeat repeat flag
* @return string content re-formatted
*/
function smarty_block_php($params, $content, $template, &$repeat)
{
if (!$template->allow_php_tag) {
throw new SmartyException("{php} is deprecated, set allow_php_tag = true to enable");
}
eval($content);
return '';
}
?>

Просмотреть файл

@ -0,0 +1,102 @@
<?php
/**
* Smarty plugin to format text blocks
*
* @package Smarty
* @subpackage PluginsBlock
*/
/**
* Smarty {textformat}{/textformat} block plugin
*
* Type: block function<br>
* Name: textformat<br>
* Purpose: format text a certain way with preset styles
* or custom wrap/indent settings<br>
*
* @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}
* (Smarty online manual)
* @param array $params parameters
* <pre>
* Params: style: string (email)
* indent: integer (0)
* wrap: integer (80)
* wrap_char string ("\n")
* indent_char: string (" ")
* wrap_boundary: boolean (true)
* </pre>
* @author Monte Ohrt <monte at ohrt dot com>
* @param string $content contents of the block
* @param object $template template object
* @param boolean &$repeat repeat flag
* @return string content re-formatted
*/
function smarty_block_textformat($params, $content, $template, &$repeat)
{
if (is_null($content)) {
return;
}
$style = null;
$indent = 0;
$indent_first = 0;
$indent_char = ' ';
$wrap = 80;
$wrap_char = "\n";
$wrap_cut = false;
$assign = null;
foreach ($params as $_key => $_val) {
switch ($_key) {
case 'style':
case 'indent_char':
case 'wrap_char':
case 'assign':
$$_key = (string)$_val;
break;
case 'indent':
case 'indent_first':
case 'wrap':
$$_key = (int)$_val;
break;
case 'wrap_cut':
$$_key = (bool)$_val;
break;
default:
trigger_error("textformat: unknown attribute '$_key'");
}
}
if ($style == 'email') {
$wrap = 72;
}
// split into paragraphs
$_paragraphs = preg_split('![\r\n][\r\n]!', $content);
$_output = '';
for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) {
if ($_paragraphs[$_x] == '') {
continue;
}
// convert mult. spaces & special chars to single space
$_paragraphs[$_x] = preg_replace(array('!\s+!', '!(^\s+)|(\s+$)!'), array(' ', ''), $_paragraphs[$_x]);
// indent first line
if ($indent_first > 0) {
$_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x];
}
// wordwrap sentences
$_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut);
// indent lines
if ($indent > 0) {
$_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]);
}
}
$_output = implode($wrap_char . $wrap_char, $_paragraphs);
return $assign ? $template->assign($assign, $_output) : $_output;
}
?>

Просмотреть файл

@ -0,0 +1,78 @@
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {counter} function plugin
*
* Type: function<br>
* Name: counter<br>
* Purpose: print out a counter value
* @author Monte Ohrt <monte at ohrt dot com>
* @link http://smarty.php.net/manual/en/language.function.counter.php {counter}
* (Smarty online manual)
* @param array parameters
* @param Smarty
* @param object $template template object
* @return string|null
*/
function smarty_function_counter($params, $template)
{
static $counters = array();
$name = (isset($params['name'])) ? $params['name'] : 'default';
if (!isset($counters[$name])) {
$counters[$name] = array(
'start'=>1,
'skip'=>1,
'direction'=>'up',
'count'=>1
);
}
$counter =& $counters[$name];
if (isset($params['start'])) {
$counter['start'] = $counter['count'] = (int)$params['start'];
}
if (!empty($params['assign'])) {
$counter['assign'] = $params['assign'];
}
if (isset($counter['assign'])) {
$template->assign($counter['assign'], $counter['count']);
}
if (isset($params['print'])) {
$print = (bool)$params['print'];
} else {
$print = empty($counter['assign']);
}
if ($print) {
$retval = $counter['count'];
} else {
$retval = null;
}
if (isset($params['skip'])) {
$counter['skip'] = $params['skip'];
}
if (isset($params['direction'])) {
$counter['direction'] = $params['direction'];
}
if ($counter['direction'] == "down")
$counter['count'] -= $counter['skip'];
else
$counter['count'] += $counter['skip'];
return $retval;
}
?>

Просмотреть файл

@ -0,0 +1,106 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {cycle} function plugin
*
* Type: function<br>
* Name: cycle<br>
* Date: May 3, 2002<br>
* Purpose: cycle through given values<br>
* Input:
* - name = name of cycle (optional)
* - values = comma separated list of values to cycle,
* or an array of values to cycle
* (this can be left out for subsequent calls)
* - reset = boolean - resets given var to true
* - print = boolean - print var or not. default is true
* - advance = boolean - whether or not to advance the cycle
* - delimiter = the value delimiter, default is ","
* - assign = boolean, assigns to template var instead of
* printed.
*
* Examples:<br>
* <pre>
* {cycle values="#eeeeee,#d0d0d0d"}
* {cycle name=row values="one,two,three" reset=true}
* {cycle name=row}
* </pre>
* @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author credit to Mark Priatel <mpriatel@rogers.com>
* @author credit to Gerard <gerard@interfold.com>
* @author credit to Jason Sweat <jsweat_php@yahoo.com>
* @version 1.3
* @param array
* @param object $template template object
* @return string|null
*/
function smarty_function_cycle($params, $template)
{
static $cycle_vars;
$name = (empty($params['name'])) ? 'default' : $params['name'];
$print = (isset($params['print'])) ? (bool)$params['print'] : true;
$advance = (isset($params['advance'])) ? (bool)$params['advance'] : true;
$reset = (isset($params['reset'])) ? (bool)$params['reset'] : false;
if (!in_array('values', array_keys($params))) {
if(!isset($cycle_vars[$name]['values'])) {
trigger_error("cycle: missing 'values' parameter");
return;
}
} else {
if(isset($cycle_vars[$name]['values'])
&& $cycle_vars[$name]['values'] != $params['values'] ) {
$cycle_vars[$name]['index'] = 0;
}
$cycle_vars[$name]['values'] = $params['values'];
}
if (isset($params['delimiter'])) {
$cycle_vars[$name]['delimiter'] = $params['delimiter'];
} elseif (!isset($cycle_vars[$name]['delimiter'])) {
$cycle_vars[$name]['delimiter'] = ',';
}
if(is_array($cycle_vars[$name]['values'])) {
$cycle_array = $cycle_vars[$name]['values'];
} else {
$cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
}
if(!isset($cycle_vars[$name]['index']) || $reset ) {
$cycle_vars[$name]['index'] = 0;
}
if (isset($params['assign'])) {
$print = false;
$template->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
}
if($print) {
$retval = $cycle_array[$cycle_vars[$name]['index']];
} else {
$retval = null;
}
if($advance) {
if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
$cycle_vars[$name]['index'] = 0;
} else {
$cycle_vars[$name]['index']++;
}
}
return $retval;
}
?>

Просмотреть файл

@ -0,0 +1,216 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {fetch} plugin
*
* Type: function<br>
* Name: fetch<br>
* Purpose: fetch file, web or ftp data and display results
* @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $params parameters
* @param object $template template object
* @return string|null if the assign parameter is passed, Smarty assigns the
* result to a template variable
*/
function smarty_function_fetch($params, $template)
{
if (empty($params['file'])) {
trigger_error("[plugin] fetch parameter 'file' cannot be empty",E_USER_NOTICE);
return;
}
$content = '';
if (isset($template->security_policy) && !preg_match('!^(http|ftp)://!i', $params['file'])) {
if(!$template->security_policy->isTrustedResourceDir($params['file'])) {
return;
}
// fetch the file
if($fp = @fopen($params['file'],'r')) {
while(!feof($fp)) {
$content .= fgets ($fp,4096);
}
fclose($fp);
} else {
trigger_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'',E_USER_NOTICE);
return;
}
} else {
// not a local file
if(preg_match('!^http://!i',$params['file'])) {
// http fetch
if($uri_parts = parse_url($params['file'])) {
// set defaults
$host = $server_name = $uri_parts['host'];
$timeout = 30;
$accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
$agent = "Smarty Template Engine ".$template->_version;
$referer = "";
$uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
$uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
$_is_proxy = false;
if(empty($uri_parts['port'])) {
$port = 80;
} else {
$port = $uri_parts['port'];
}
if(!empty($uri_parts['user'])) {
$user = $uri_parts['user'];
}
if(!empty($uri_parts['pass'])) {
$pass = $uri_parts['pass'];
}
// loop through parameters, setup headers
foreach($params as $param_key => $param_value) {
switch($param_key) {
case "file":
case "assign":
case "assign_headers":
break;
case "user":
if(!empty($param_value)) {
$user = $param_value;
}
break;
case "pass":
if(!empty($param_value)) {
$pass = $param_value;
}
break;
case "accept":
if(!empty($param_value)) {
$accept = $param_value;
}
break;
case "header":
if(!empty($param_value)) {
if(!preg_match('![\w\d-]+: .+!',$param_value)) {
trigger_error("[plugin] invalid header format '".$param_value."'",E_USER_NOTICE);
return;
} else {
$extra_headers[] = $param_value;
}
}
break;
case "proxy_host":
if(!empty($param_value)) {
$proxy_host = $param_value;
}
break;
case "proxy_port":
if(!preg_match('!\D!', $param_value)) {
$proxy_port = (int) $param_value;
} else {
trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE);
return;
}
break;
case "agent":
if(!empty($param_value)) {
$agent = $param_value;
}
break;
case "referer":
if(!empty($param_value)) {
$referer = $param_value;
}
break;
case "timeout":
if(!preg_match('!\D!', $param_value)) {
$timeout = (int) $param_value;
} else {
trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE);
return;
}
break;
default:
trigger_error("[plugin] unrecognized attribute '".$param_key."'",E_USER_NOTICE);
return;
}
}
if(!empty($proxy_host) && !empty($proxy_port)) {
$_is_proxy = true;
$fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
} else {
$fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
}
if(!$fp) {
trigger_error("[plugin] unable to fetch: $errstr ($errno)",E_USER_NOTICE);
return;
} else {
if($_is_proxy) {
fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
} else {
fputs($fp, "GET $uri HTTP/1.0\r\n");
}
if(!empty($host)) {
fputs($fp, "Host: $host\r\n");
}
if(!empty($accept)) {
fputs($fp, "Accept: $accept\r\n");
}
if(!empty($agent)) {
fputs($fp, "User-Agent: $agent\r\n");
}
if(!empty($referer)) {
fputs($fp, "Referer: $referer\r\n");
}
if(isset($extra_headers) && is_array($extra_headers)) {
foreach($extra_headers as $curr_header) {
fputs($fp, $curr_header."\r\n");
}
}
if(!empty($user) && !empty($pass)) {
fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
}
fputs($fp, "\r\n");
while(!feof($fp)) {
$content .= fgets($fp,4096);
}
fclose($fp);
$csplit = preg_split("!\r\n\r\n!",$content,2);
$content = $csplit[1];
if(!empty($params['assign_headers'])) {
$template->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0]));
}
}
} else {
trigger_error("[plugin fetch] unable to parse URL, check syntax",E_USER_NOTICE);
return;
}
} else {
// ftp fetch
if($fp = @fopen($params['file'],'r')) {
while(!feof($fp)) {
$content .= fgets ($fp,4096);
}
fclose($fp);
} else {
trigger_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'',E_USER_NOTICE);
return;
}
}
}
if (!empty($params['assign'])) {
$template->assign($params['assign'],$content);
} else {
return $content;
}
}
?>

Просмотреть файл

@ -0,0 +1,143 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_checkboxes} function plugin
*
* File: function.html_checkboxes.php<br>
* Type: function<br>
* Name: html_checkboxes<br>
* Date: 24.Feb.2003<br>
* Purpose: Prints out a list of checkbox input types<br>
* Examples:
* <pre>
* {html_checkboxes values=$ids output=$names}
* {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
* {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
* </pre>
* @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
* (Smarty online manual)
* @author Christopher Kvarme <christopher.kvarme@flashjab.com>
* @author credits to Monte Ohrt <monte at ohrt dot com>
* @version 1.0
* @param array $params parameters
* Input:<br>
* - name (optional) - string default "checkbox"
* - values (required) - array
* - options (optional) - associative array
* - checked (optional) - array default not set
* - separator (optional) - ie <br> or &nbsp;
* - output (optional) - the output next to each checkbox
* - assign (optional) - assign the output as an array to this variable
* @param object $template template object
* @return string
* @uses smarty_function_escape_special_chars()
*/
function smarty_function_html_checkboxes($params, $template)
{
require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
$name = 'checkbox';
$values = null;
$options = null;
$selected = null;
$separator = '';
$labels = true;
$output = null;
$extra = '';
foreach($params as $_key => $_val) {
switch($_key) {
case 'name':
case 'separator':
$$_key = $_val;
break;
case 'labels':
$$_key = (bool)$_val;
break;
case 'options':
$$_key = (array)$_val;
break;
case 'values':
case 'output':
$$_key = array_values((array)$_val);
break;
case 'checked':
case 'selected':
$selected = array_map('strval', array_values((array)$_val));
break;
case 'checkboxes':
trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
$options = (array)$_val;
break;
case 'assign':
break;
default:
if(!is_array($_val)) {
$extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
} else {
trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
}
break;
}
}
if (!isset($options) && !isset($values))
return ''; /* raise error here? */
settype($selected, 'array');
$_html_result = array();
if (isset($options)) {
foreach ($options as $_key=>$_val)
$_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
} else {
foreach ($values as $_i=>$_key) {
$_val = isset($output[$_i]) ? $output[$_i] : '';
$_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
}
}
if(!empty($params['assign'])) {
$template->assign($params['assign'], $_html_result);
} else {
return implode("\n",$_html_result);
}
}
function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {
$_output = '';
if ($labels) $_output .= '<label>';
$_output .= '<input type="checkbox" name="'
. smarty_function_escape_special_chars($name) . '[]" value="'
. smarty_function_escape_special_chars($value) . '"';
if (in_array((string)$value, $selected)) {
$_output .= ' checked="checked"';
}
$_output .= $extra . ' />' . $output;
if ($labels) $_output .= '</label>';
$_output .= $separator;
return $_output;
}
?>

Просмотреть файл

@ -0,0 +1,137 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_image} function plugin
*
* Type: function<br>
* Name: html_image<br>
* Date: Feb 24, 2003<br>
* Purpose: format HTML tags for the image<br>
* Examples: {html_image file="/images/masthead.gif"}
* Output: <img src="/images/masthead.gif" width=400 height=23>
*
* @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author credits to Duda <duda@big.hu>
* @version 1.0
* @param array $params parameters
* Input:<br>
* - file = file (and path) of image (required)
* - height = image height (optional, default actual height)
* - width = image width (optional, default actual width)
* - basedir = base directory for absolute paths, default
* is environment variable DOCUMENT_ROOT
* - path_prefix = prefix for path output (optional, default empty)
* @param object $template template object
* @return string
* @uses smarty_function_escape_special_chars()
*/
function smarty_function_html_image($params, $template)
{
require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
$alt = '';
$file = '';
$height = '';
$width = '';
$extra = '';
$prefix = '';
$suffix = '';
$path_prefix = '';
$server_vars = $_SERVER;
$basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : '';
foreach($params as $_key => $_val) {
switch ($_key) {
case 'file':
case 'height':
case 'width':
case 'dpi':
case 'path_prefix':
case 'basedir':
$$_key = $_val;
break;
case 'alt':
if (!is_array($_val)) {
$$_key = smarty_function_escape_special_chars($_val);
} else {
throw new SmartyException ("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
}
break;
case 'link':
case 'href':
$prefix = '<a href="' . $_val . '">';
$suffix = '</a>';
break;
default:
if (!is_array($_val)) {
$extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
} else {
throw new SmartyException ("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
}
break;
}
}
if (empty($file)) {
trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE);
return;
}
if (substr($file, 0, 1) == '/') {
$_image_path = $basedir . $file;
} else {
$_image_path = $file;
}
if (!isset($params['width']) || !isset($params['height'])) {
if (!$_image_data = @getimagesize($_image_path)) {
if (!file_exists($_image_path)) {
trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
return;
} else if (!is_readable($_image_path)) {
trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
return;
} else {
trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
return;
}
}
if (isset($template->security_policy)) {
if (!$template->security_policy->isTrustedResourceDir($_image_path)) {
return;
}
}
if (!isset($params['width'])) {
$width = $_image_data[0];
}
if (!isset($params['height'])) {
$height = $_image_data[1];
}
}
if (isset($params['dpi'])) {
if (strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {
$dpi_default = 72;
} else {
$dpi_default = 96;
}
$_resize = $dpi_default / $params['dpi'];
$width = round($width * $_resize);
$height = round($height * $_resize);
}
return $prefix . '<img src="' . $path_prefix . $file . '" alt="' . $alt . '" width="' . $width . '" height="' . $height . '"' . $extra . ' />' . $suffix;
}
?>

Просмотреть файл

@ -0,0 +1,119 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_options} function plugin
*
* Type: function<br>
* Name: html_options<br>
* Purpose: Prints the list of <option> tags generated from
* the passed parameters
*
* @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $params parameters
* Input:<br>
* - name (optional) - string default "select"
* - values (required if no options supplied) - array
* - options (required if no values supplied) - associative array
* - selected (optional) - string default not set
* - output (required if not options supplied) - array
* @param object $template template object
* @return string
* @uses smarty_function_escape_special_chars()
*/
function smarty_function_html_options($params, $template)
{
require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
$name = null;
$values = null;
$options = null;
$selected = array();
$output = null;
$extra = '';
foreach($params as $_key => $_val) {
switch ($_key) {
case 'name':
$$_key = (string)$_val;
break;
case 'options':
$$_key = (array)$_val;
break;
case 'values':
case 'output':
$$_key = array_values((array)$_val);
break;
case 'selected':
$$_key = array_map('strval', array_values((array)$_val));
break;
default:
if (!is_array($_val)) {
$extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
} else {
trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
}
break;
}
}
if (!isset($options) && !isset($values))
return '';
/* raise error here? */
$_html_result = '';
if (isset($options)) {
foreach ($options as $_key => $_val)
$_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
} else {
foreach ($values as $_i => $_key) {
$_val = isset($output[$_i]) ? $output[$_i] : '';
$_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
}
}
if (!empty($name)) {
$_html_result = '<select name="' . $name . '"' . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
}
return $_html_result;
}
function smarty_function_html_options_optoutput($key, $value, $selected)
{
if (!is_array($value)) {
$_html_result = '<option value="' .
smarty_function_escape_special_chars($key) . '"';
if (in_array((string)$key, $selected))
$_html_result .= ' selected="selected"';
$_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . "\n";
} else {
$_html_result = smarty_function_html_options_optgroup($key, $value, $selected);
}
return $_html_result;
}
function smarty_function_html_options_optgroup($key, $values, $selected)
{
$optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
foreach ($values as $key => $value) {
$optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);
}
$optgroup_html .= "</optgroup>\n";
return $optgroup_html;
}
?>

Просмотреть файл

@ -0,0 +1,154 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_radios} function plugin
*
* File: function.html_radios.php<br>
* Type: function<br>
* Name: html_radios<br>
* Date: 24.Feb.2003<br>
* Purpose: Prints out a list of radio input types<br>
* Examples:
* <pre>
* {html_radios values=$ids output=$names}
* {html_radios values=$ids name='box' separator='<br>' output=$names}
* {html_radios values=$ids checked=$checked separator='<br>' output=$names}
* </pre>
*
* @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
* (Smarty online manual)
* @author Christopher Kvarme <christopher.kvarme@flashjab.com>
* @author credits to Monte Ohrt <monte at ohrt dot com>
* @version 1.0
* @param array $params parameters
* Input:<br>
* - name (optional) - string default "radio"
* - values (required) - array
* - options (optional) - associative array
* - checked (optional) - array default not set
* - separator (optional) - ie <br> or &nbsp;
* - output (optional) - the output next to each radio button
* - assign (optional) - assign the output as an array to this variable
* @param object $template template object
* @return string
* @uses smarty_function_escape_special_chars()
*/
function smarty_function_html_radios($params, $template)
{
require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
$name = 'radio';
$values = null;
$options = null;
$selected = null;
$separator = '';
$labels = true;
$label_ids = false;
$output = null;
$extra = '';
foreach($params as $_key => $_val) {
switch ($_key) {
case 'name':
case 'separator':
$$_key = (string)$_val;
break;
case 'checked':
case 'selected':
if (is_array($_val)) {
trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
} else {
$selected = (string)$_val;
}
break;
case 'labels':
case 'label_ids':
$$_key = (bool)$_val;
break;
case 'options':
$$_key = (array)$_val;
break;
case 'values':
case 'output':
$$_key = array_values((array)$_val);
break;
case 'radios':
trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
$options = (array)$_val;
break;
case 'assign':
break;
default:
if (!is_array($_val)) {
$extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
} else {
trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
}
break;
}
}
if (!isset($options) && !isset($values))
return '';
/* raise error here? */
$_html_result = array();
if (isset($options)) {
foreach ($options as $_key => $_val)
$_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);
} else {
foreach ($values as $_i => $_key) {
$_val = isset($output[$_i]) ? $output[$_i] : '';
$_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);
}
}
if (!empty($params['assign'])) {
$template->assign($params['assign'], $_html_result);
} else {
return implode("\n", $_html_result);
}
}
function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids)
{
$_output = '';
if ($labels) {
if ($label_ids) {
$_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!', '_', $name . '_' . $value));
$_output .= '<label for="' . $_id . '">';
} else {
$_output .= '<label>';
}
}
$_output .= '<input type="radio" name="'
. smarty_function_escape_special_chars($name) . '" value="'
. smarty_function_escape_special_chars($value) . '"';
if ($labels && $label_ids) $_output .= ' id="' . $_id . '"';
if ((string)$value == $selected) {
$_output .= ' checked="checked"';
}
$_output .= $extra . ' />' . $output;
if ($labels) $_output .= '</label>';
$_output .= $separator;
return $_output;
}
?>

Просмотреть файл

@ -0,0 +1,330 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_select_date} plugin
*
* Type: function<br>
* Name: html_select_date<br>
* Purpose: Prints the dropdowns for date selection.
*
* ChangeLog:<br>
* - 1.0 initial release
* - 1.1 added support for +/- N syntax for begin
* and end year values. (Monte)
* - 1.2 added support for yyyy-mm-dd syntax for
* time value. (Jan Rosier)
* - 1.3 added support for choosing format for
* month values (Gary Loescher)
* - 1.3.1 added support for choosing format for
* day values (Marcus Bointon)
* - 1.3.2 support negative timestamps, force year
* dropdown to include given date unless explicitly set (Monte)
* - 1.3.4 fix behaviour of 0000-00-00 00:00:00 dates to match that
* of 0000-00-00 dates (cybot, boots)
*
* @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
* (Smarty online manual)
* @version 1.3.4
* @author Andrei Zmievski
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $params parameters
* @param object $template template object
* @return string
*/
function smarty_function_html_select_date($params, $template)
{
require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
require_once(SMARTY_PLUGINS_DIR . 'function.html_options.php');
/* Default values. */
$prefix = "Date_";
$start_year = strftime("%Y");
$end_year = $start_year;
$display_days = true;
$display_months = true;
$display_years = true;
$month_format = "%B";
/* Write months as numbers by default GL */
$month_value_format = "%m";
$day_format = "%02d";
/* Write day values using this format MB */
$day_value_format = "%d";
$year_as_text = false;
/* Display years in reverse order? Ie. 2000,1999,.... */
$reverse_years = false;
/* Should the select boxes be part of an array when returned from PHP?
e.g. setting it to "birthday", would create "birthday[Day]",
"birthday[Month]" & "birthday[Year]". Can be combined with prefix */
$field_array = null;
/* <select size>'s of the different <select> tags.
If not set, uses default dropdown. */
$day_size = null;
$month_size = null;
$year_size = null;
/* Unparsed attributes common to *ALL* the <select>/<input> tags.
An example might be in the template: all_extra ='class ="foo"'. */
$all_extra = null;
/* Separate attributes for the tags. */
$day_extra = null;
$month_extra = null;
$year_extra = null;
/* Order in which to display the fields.
"D" -> day, "M" -> month, "Y" -> year. */
$field_order = 'MDY';
/* String printed between the different fields. */
$field_separator = "\n";
$time = time();
$all_empty = null;
$day_empty = null;
$month_empty = null;
$year_empty = null;
$extra_attrs = '';
foreach ($params as $_key => $_value) {
switch ($_key) {
case 'prefix':
case 'time':
case 'start_year':
case 'end_year':
case 'month_format':
case 'day_format':
case 'day_value_format':
case 'field_array':
case 'day_size':
case 'month_size':
case 'year_size':
case 'all_extra':
case 'day_extra':
case 'month_extra':
case 'year_extra':
case 'field_order':
case 'field_separator':
case 'month_value_format':
case 'month_empty':
case 'day_empty':
case 'year_empty':
$$_key = (string)$_value;
break;
case 'all_empty':
$$_key = (string)$_value;
$day_empty = $month_empty = $year_empty = $all_empty;
break;
case 'display_days':
case 'display_months':
case 'display_years':
case 'year_as_text':
case 'reverse_years':
$$_key = (bool)$_value;
break;
default:
if (!is_array($_value)) {
$extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
} else {
trigger_error("html_select_date: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
}
break;
}
}
if (preg_match('!^-\d+$!', $time)) {
// negative timestamp, use date()
$time = date('Y-m-d', $time);
}
// If $time is not in format yyyy-mm-dd
if (preg_match('/^(\d{0,4}-\d{0,2}-\d{0,2})/', $time, $found)) {
$time = $found[1];
} else {
// use smarty_make_timestamp to get an unix timestamp and
// strftime to make yyyy-mm-dd
$time = strftime('%Y-%m-%d', smarty_make_timestamp($time));
}
// Now split this in pieces, which later can be used to set the select
$time = explode("-", $time);
// make syntax "+N" or "-N" work with start_year and end_year
if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) {
if ($match[1] == '+') {
$end_year = strftime('%Y') + $match[2];
} else {
$end_year = strftime('%Y') - $match[2];
}
}
if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) {
if ($match[1] == '+') {
$start_year = strftime('%Y') + $match[2];
} else {
$start_year = strftime('%Y') - $match[2];
}
}
if (strlen($time[0]) > 0) {
if ($start_year > $time[0] && !isset($params['start_year'])) {
// force start year to include given date if not explicitly set
$start_year = $time[0];
}
if ($end_year < $time[0] && !isset($params['end_year'])) {
// force end year to include given date if not explicitly set
$end_year = $time[0];
}
}
$field_order = strtoupper($field_order);
$html_result = $month_result = $day_result = $year_result = "";
$field_separator_count = -1;
if ($display_months) {
$field_separator_count++;
$month_names = array();
$month_values = array();
if (isset($month_empty)) {
$month_names[''] = $month_empty;
$month_values[''] = '';
}
for ($i = 1; $i <= 12; $i++) {
$month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
$month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));
}
$month_result .= '<select name=';
if (null !== $field_array) {
$month_result .= '"' . $field_array . '[' . $prefix . 'Month]"';
} else {
$month_result .= '"' . $prefix . 'Month"';
}
if (null !== $month_size) {
$month_result .= ' size="' . $month_size . '"';
}
if (null !== $month_extra) {
$month_result .= ' ' . $month_extra;
}
if (null !== $all_extra) {
$month_result .= ' ' . $all_extra;
}
$month_result .= $extra_attrs . '>' . "\n";
$month_result .= smarty_function_html_options(array('output' => $month_names,
'values' => $month_values,
'selected' => (int)$time[1] ? strftime($month_value_format, mktime(0, 0, 0, (int)$time[1], 1, 2000)) : '',
'print_result' => false),
$template);
$month_result .= '</select>';
}
if ($display_days) {
$field_separator_count++;
$days = array();
if (isset($day_empty)) {
$days[''] = $day_empty;
$day_values[''] = '';
}
for ($i = 1; $i <= 31; $i++) {
$days[] = sprintf($day_format, $i);
$day_values[] = sprintf($day_value_format, $i);
}
$day_result .= '<select name=';
if (null !== $field_array) {
$day_result .= '"' . $field_array . '[' . $prefix . 'Day]"';
} else {
$day_result .= '"' . $prefix . 'Day"';
}
if (null !== $day_size) {
$day_result .= ' size="' . $day_size . '"';
}
if (null !== $all_extra) {
$day_result .= ' ' . $all_extra;
}
if (null !== $day_extra) {
$day_result .= ' ' . $day_extra;
}
$day_result .= $extra_attrs . '>' . "\n";
$day_result .= smarty_function_html_options(array('output' => $days,
'values' => $day_values,
'selected' => $time[2],
'print_result' => false),
$template);
$day_result .= '</select>';
}
if ($display_years) {
$field_separator_count++;
if (null !== $field_array) {
$year_name = $field_array . '[' . $prefix . 'Year]';
} else {
$year_name = $prefix . 'Year';
}
if ($year_as_text) {
$year_result .= '<input type="text" name="' . $year_name . '" value="' . $time[0] . '" size="4" maxlength="4"';
if (null !== $all_extra) {
$year_result .= ' ' . $all_extra;
}
if (null !== $year_extra) {
$year_result .= ' ' . $year_extra;
}
$year_result .= ' />';
} else {
$years = range((int)$start_year, (int)$end_year);
if ($reverse_years) {
rsort($years, SORT_NUMERIC);
} else {
sort($years, SORT_NUMERIC);
}
$yearvals = $years;
if (isset($year_empty)) {
array_unshift($years, $year_empty);
array_unshift($yearvals, '');
}
$year_result .= '<select name="' . $year_name . '"';
if (null !== $year_size) {
$year_result .= ' size="' . $year_size . '"';
}
if (null !== $all_extra) {
$year_result .= ' ' . $all_extra;
}
if (null !== $year_extra) {
$year_result .= ' ' . $year_extra;
}
$year_result .= $extra_attrs . '>' . "\n";
$year_result .= smarty_function_html_options(array('output' => $years,
'values' => $yearvals,
'selected' => $time[0],
'print_result' => false),
$template);
$year_result .= '</select>';
}
}
// Loop thru the field_order field
for ($i = 0; $i <= 2; $i++) {
$c = substr($field_order, $i, 1);
switch ($c) {
case 'D':
$html_result .= $day_result;
break;
case 'M':
$html_result .= $month_result;
break;
case 'Y':
$html_result .= $year_result;
break;
}
// Add the field seperator
if ($i < $field_separator_count) {
$html_result .= $field_separator;
}
}
return $html_result;
}
?>

Просмотреть файл

@ -0,0 +1,194 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_select_time} function plugin
*
* Type: function<br>
* Name: html_select_time<br>
* Purpose: Prints the dropdowns for time selection
*
* @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}
* (Smarty online manual)
* @author Roberto Berto <roberto@berto.net>
* @credits Monte Ohrt <monte AT ohrt DOT com>
* @param array $params parameters
* @param object $template template object
* @return string
* @uses smarty_make_timestamp()
*/
function smarty_function_html_select_time($params, $template)
{
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
require_once(SMARTY_PLUGINS_DIR . 'function.html_options.php');
/* Default values. */
$prefix = "Time_";
$time = time();
$display_hours = true;
$display_minutes = true;
$display_seconds = true;
$display_meridian = true;
$use_24_hours = true;
$minute_interval = 1;
$second_interval = 1;
/* Should the select boxes be part of an array when returned from PHP?
e.g. setting it to "birthday", would create "birthday[Hour]",
"birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]".
Can be combined with prefix. */
$field_array = null;
$all_extra = null;
$hour_extra = null;
$minute_extra = null;
$second_extra = null;
$meridian_extra = null;
foreach ($params as $_key => $_value) {
switch ($_key) {
case 'prefix':
case 'time':
case 'field_array':
case 'all_extra':
case 'hour_extra':
case 'minute_extra':
case 'second_extra':
case 'meridian_extra':
$$_key = (string)$_value;
break;
case 'display_hours':
case 'display_minutes':
case 'display_seconds':
case 'display_meridian':
case 'use_24_hours':
$$_key = (bool)$_value;
break;
case 'minute_interval':
case 'second_interval':
$$_key = (int)$_value;
break;
default:
trigger_error("[html_select_time] unknown parameter $_key", E_USER_WARNING);
}
}
$time = smarty_make_timestamp($time);
$html_result = '';
if ($display_hours) {
$hours = $use_24_hours ? range(0, 23) : range(1, 12);
$hour_fmt = $use_24_hours ? '%H' : '%I';
for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)
$hours[$i] = sprintf('%02d', $hours[$i]);
$html_result .= '<select name=';
if (null !== $field_array) {
$html_result .= '"' . $field_array . '[' . $prefix . 'Hour]"';
} else {
$html_result .= '"' . $prefix . 'Hour"';
}
if (null !== $hour_extra) {
$html_result .= ' ' . $hour_extra;
}
if (null !== $all_extra) {
$html_result .= ' ' . $all_extra;
}
$html_result .= '>' . "\n";
$html_result .= smarty_function_html_options(array('output' => $hours,
'values' => $hours,
'selected' => strftime($hour_fmt, $time),
'print_result' => false),
$template);
$html_result .= "</select>\n";
}
if ($display_minutes) {
$all_minutes = range(0, 59);
for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i += $minute_interval)
$minutes[] = sprintf('%02d', $all_minutes[$i]);
$selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);
$html_result .= '<select name=';
if (null !== $field_array) {
$html_result .= '"' . $field_array . '[' . $prefix . 'Minute]"';
} else {
$html_result .= '"' . $prefix . 'Minute"';
}
if (null !== $minute_extra) {
$html_result .= ' ' . $minute_extra;
}
if (null !== $all_extra) {
$html_result .= ' ' . $all_extra;
}
$html_result .= '>' . "\n";
$html_result .= smarty_function_html_options(array('output' => $minutes,
'values' => $minutes,
'selected' => $selected,
'print_result' => false),
$template);
$html_result .= "</select>\n";
}
if ($display_seconds) {
$all_seconds = range(0, 59);
for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i += $second_interval)
$seconds[] = sprintf('%02d', $all_seconds[$i]);
$selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);
$html_result .= '<select name=';
if (null !== $field_array) {
$html_result .= '"' . $field_array . '[' . $prefix . 'Second]"';
} else {
$html_result .= '"' . $prefix . 'Second"';
}
if (null !== $second_extra) {
$html_result .= ' ' . $second_extra;
}
if (null !== $all_extra) {
$html_result .= ' ' . $all_extra;
}
$html_result .= '>' . "\n";
$html_result .= smarty_function_html_options(array('output' => $seconds,
'values' => $seconds,
'selected' => $selected,
'print_result' => false),
$template);
$html_result .= "</select>\n";
}
if ($display_meridian && !$use_24_hours) {
$html_result .= '<select name=';
if (null !== $field_array) {
$html_result .= '"' . $field_array . '[' . $prefix . 'Meridian]"';
} else {
$html_result .= '"' . $prefix . 'Meridian"';
}
if (null !== $meridian_extra) {
$html_result .= ' ' . $meridian_extra;
}
if (null !== $all_extra) {
$html_result .= ' ' . $all_extra;
}
$html_result .= '>' . "\n";
$html_result .= smarty_function_html_options(array('output' => array('AM', 'PM'),
'values' => array('am', 'pm'),
'selected' => strtolower(strftime('%p', $time)),
'print_result' => false),
$template);
$html_result .= "</select>\n";
}
return $html_result;
}
?>

Просмотреть файл

@ -0,0 +1,177 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {html_table} function plugin
*
* Type: function<br>
* Name: html_table<br>
* Date: Feb 17, 2003<br>
* Purpose: make an html table from an array of data<br>
*
*
* Examples:
* <pre>
* {table loop=$data}
* {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
* {table loop=$data cols="first,second,third" tr_attr=$colors}
* </pre>
*
* @author Monte Ohrt <monte at ohrt dot com>
* @author credit to Messju Mohr <messju at lammfellpuschen dot de>
* @author credit to boots <boots dot smarty at yahoo dot com>
* @version 1.1
* @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}
* (Smarty online manual)
* @param array $params parameters
* Input:<br>
* - loop = array to loop through
* - cols = number of columns, comma separated list of column names
* or array of column names
* - rows = number of rows
* - table_attr = table attributes
* - th_attr = table heading attributes (arrays are cycled)
* - tr_attr = table row attributes (arrays are cycled)
* - td_attr = table cell attributes (arrays are cycled)
* - trailpad = value to pad trailing cells with
* - caption = text for caption element
* - vdir = vertical direction (default: "down", means top-to-bottom)
* - hdir = horizontal direction (default: "right", means left-to-right)
* - inner = inner loop (default "cols": print $loop line by line,
* $loop will be printed column by column otherwise)
* @param object $template template object
* @return string
*/
function smarty_function_html_table($params, $template)
{
$table_attr = 'border="1"';
$tr_attr = '';
$th_attr = '';
$td_attr = '';
$cols = $cols_count = 3;
$rows = 3;
$trailpad = '&nbsp;';
$vdir = 'down';
$hdir = 'right';
$inner = 'cols';
$caption = '';
$loop = null;
if (!isset($params['loop'])) {
trigger_error("html_table: missing 'loop' parameter",E_USER_WARNING);
return;
}
foreach ($params as $_key => $_value) {
switch ($_key) {
case 'loop':
$$_key = (array)$_value;
break;
case 'cols':
if (is_array($_value) && !empty($_value)) {
$cols = $_value;
$cols_count = count($_value);
} elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {
$cols = explode(',', $_value);
$cols_count = count($cols);
} elseif (!empty($_value)) {
$cols_count = (int)$_value;
} else {
$cols_count = $cols;
}
break;
case 'rows':
$$_key = (int)$_value;
break;
case 'table_attr':
case 'trailpad':
case 'hdir':
case 'vdir':
case 'inner':
case 'caption':
$$_key = (string)$_value;
break;
case 'tr_attr':
case 'td_attr':
case 'th_attr':
$$_key = $_value;
break;
}
}
$loop_count = count($loop);
if (empty($params['rows'])) {
/* no rows specified */
$rows = ceil($loop_count / $cols_count);
} elseif (empty($params['cols'])) {
if (!empty($params['rows'])) {
/* no cols specified, but rows */
$cols_count = ceil($loop_count / $rows);
}
}
$output = "<table $table_attr>\n";
if (!empty($caption)) {
$output .= '<caption>' . $caption . "</caption>\n";
}
if (is_array($cols)) {
$cols = ($hdir == 'right') ? $cols : array_reverse($cols);
$output .= "<thead><tr>\n";
for ($r = 0; $r < $cols_count; $r++) {
$output .= '<th' . smarty_function_html_table_cycle('th', $th_attr, $r) . '>';
$output .= $cols[$r];
$output .= "</th>\n";
}
$output .= "</tr></thead>\n";
}
$output .= "<tbody>\n";
for ($r = 0; $r < $rows; $r++) {
$output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
$rx = ($vdir == 'down') ? $r * $cols_count : ($rows-1 - $r) * $cols_count;
for ($c = 0; $c < $cols_count; $c++) {
$x = ($hdir == 'right') ? $rx + $c : $rx + $cols_count-1 - $c;
if ($inner != 'cols') {
/* shuffle x to loop over rows*/
$x = floor($x / $cols_count) + ($x % $cols_count) * $rows;
}
if ($x < $loop_count) {
$output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
} else {
$output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
}
}
$output .= "</tr>\n";
}
$output .= "</tbody>\n";
$output .= "</table>\n";
return $output;
}
function smarty_function_html_table_cycle($name, $var, $no)
{
if (!is_array($var)) {
$ret = $var;
} else {
$ret = $var[$no % count($var)];
}
return ($ret) ? ' ' . $ret : '';
}
?>

Просмотреть файл

@ -0,0 +1,156 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {mailto} function plugin
*
* Type: function<br>
* Name: mailto<br>
* Date: May 21, 2002
* Purpose: automate mailto address link creation, and optionally
* encode them.<br>
*
* Examples:
* <pre>
* {mailto address="me@domain.com"}
* {mailto address="me@domain.com" encode="javascript"}
* {mailto address="me@domain.com" encode="hex"}
* {mailto address="me@domain.com" subject="Hello to you!"}
* {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
* {mailto address="me@domain.com" extra='class="mailto"'}
* </pre>
*
* @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
* (Smarty online manual)
* @version 1.2
* @author Monte Ohrt <monte at ohrt dot com>
* @author credits to Jason Sweat (added cc, bcc and subject functionality)
* @param array $params parameters
* Input:<br>
* - address = e-mail address
* - text = (optional) text to display, default is address
* - encode = (optional) can be one of:
* * none : no encoding (default)
* * javascript : encode with javascript
* * javascript_charcode : encode with javascript charcode
* * hex : encode with hexidecimal (no javascript)
* - cc = (optional) address(es) to carbon copy
* - bcc = (optional) address(es) to blind carbon copy
* - subject = (optional) e-mail subject
* - newsgroups = (optional) newsgroup(s) to post to
* - followupto = (optional) address(es) to follow up to
* - extra = (optional) extra tags for the href link
* @param object $template template object
* @return string
*/
function smarty_function_mailto($params, $template)
{
$extra = '';
if (empty($params['address'])) {
trigger_error("mailto: missing 'address' parameter",E_USER_WARNING);
return;
} else {
$address = $params['address'];
}
$text = $address;
// netscape and mozilla do not decode %40 (@) in BCC field (bug?)
// so, don't encode it.
$search = array('%40', '%2C');
$replace = array('@', ',');
$mail_parms = array();
foreach ($params as $var => $value) {
switch ($var) {
case 'cc':
case 'bcc':
case 'followupto':
if (!empty($value))
$mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value));
break;
case 'subject':
case 'newsgroups':
$mail_parms[] = $var . '=' . rawurlencode($value);
break;
case 'extra':
case 'text':
$$var = $value;
default:
}
}
$mail_parm_vals = '';
for ($i = 0; $i < count($mail_parms); $i++) {
$mail_parm_vals .= (0 == $i) ? '?' : '&';
$mail_parm_vals .= $mail_parms[$i];
}
$address .= $mail_parm_vals;
$encode = (empty($params['encode'])) ? 'none' : $params['encode'];
if (!in_array($encode, array('javascript', 'javascript_charcode', 'hex', 'none'))) {
trigger_error("mailto: 'encode' parameter must be none, javascript or hex",E_USER_WARNING);
return;
}
if ($encode == 'javascript') {
$string = 'document.write(\'<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>\');';
$js_encode = '';
for ($x = 0; $x < strlen($string); $x++) {
$js_encode .= '%' . bin2hex($string[$x]);
}
return '<script type="text/javascript">eval(unescape(\'' . $js_encode . '\'))</script>';
} elseif ($encode == 'javascript_charcode') {
$string = '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
for($x = 0, $y = strlen($string); $x < $y; $x++) {
$ord[] = ord($string[$x]);
}
$_ret = "<script type=\"text/javascript\" language=\"javascript\">\n";
$_ret .= "<!--\n";
$_ret .= "{document.write(String.fromCharCode(";
$_ret .= implode(',', $ord);
$_ret .= "))";
$_ret .= "}\n";
$_ret .= "//-->\n";
$_ret .= "</script>\n";
return $_ret;
} elseif ($encode == 'hex') {
preg_match('!^(.*)(\?.*)$!', $address, $match);
if (!empty($match[2])) {
trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.",E_USER_WARNING);
return;
}
$address_encode = '';
for ($x = 0; $x < strlen($address); $x++) {
if (preg_match('!\w!', $address[$x])) {
$address_encode .= '%' . bin2hex($address[$x]);
} else {
$address_encode .= $address[$x];
}
}
$text_encode = '';
for ($x = 0; $x < strlen($text); $x++) {
$text_encode .= '&#x' . bin2hex($text[$x]) . ';';
}
$mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;";
return '<a href="' . $mailto . $address_encode . '" ' . $extra . '>' . $text_encode . '</a>';
} else {
// no encoding
return '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
}
}
?>

Просмотреть файл

@ -0,0 +1,83 @@
<?php
/**
* Smarty plugin
*
* This plugin is only for Smarty2 BC
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {math} function plugin
*
* Type: function<br>
* Name: math<br>
* Purpose: handle math computations in template<br>
* @link http://smarty.php.net/manual/en/language.function.math.php {math}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $params parameters
* @param object $template template object
* @return string|null
*/
function smarty_function_math($params, $template)
{
// be sure equation parameter is present
if (empty($params['equation'])) {
trigger_error("math: missing equation parameter",E_USER_WARNING);
return;
}
$equation = $params['equation'];
// make sure parenthesis are balanced
if (substr_count($equation,"(") != substr_count($equation,")")) {
trigger_error("math: unbalanced parenthesis",E_USER_WARNING);
return;
}
// match all vars in equation, make sure all are passed
preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match);
$allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
foreach($match[1] as $curr_var) {
if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
trigger_error("math: function call $curr_var not allowed",E_USER_WARNING);
return;
}
}
foreach($params as $key => $val) {
if ($key != "equation" && $key != "format" && $key != "assign") {
// make sure value is not empty
if (strlen($val)==0) {
trigger_error("math: parameter $key is empty",E_USER_WARNING);
return;
}
if (!is_numeric($val)) {
trigger_error("math: parameter $key: is not numeric",E_USER_WARNING);
return;
}
$equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation);
}
}
$smarty_math_result = null;
eval("\$smarty_math_result = ".$equation.";");
if (empty($params['format'])) {
if (empty($params['assign'])) {
return $smarty_math_result;
} else {
$template->assign($params['assign'],$smarty_math_result);
}
} else {
if (empty($params['assign'])){
printf($params['format'],$smarty_math_result);
} else {
$template->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
}
}
}
?>

Просмотреть файл

@ -0,0 +1,118 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {popup} function plugin
*
* Type: function<br>
* Name: popup<br>
* Purpose: make text pop up in windows via overlib
* @link http://smarty.php.net/manual/en/language.function.popup.php {popup}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $params parameters
* @param object $template template object
* @return string
*/
function smarty_function_popup($params, $template)
{
$append = '';
foreach ($params as $_key=>$_value) {
switch ($_key) {
case 'text':
case 'trigger':
case 'function':
case 'inarray':
$$_key = (string)$_value;
if ($_key == 'function' || $_key == 'inarray')
$append .= ',' . strtoupper($_key) . ",'$_value'";
break;
case 'caption':
case 'closetext':
case 'status':
$append .= ',' . strtoupper($_key) . ",'" . str_replace("'","\'",$_value) . "'";
break;
case 'fgcolor':
case 'bgcolor':
case 'textcolor':
case 'capcolor':
case 'closecolor':
case 'textfont':
case 'captionfont':
case 'closefont':
case 'fgbackground':
case 'bgbackground':
case 'caparray':
case 'capicon':
case 'background':
case 'frame':
$append .= ',' . strtoupper($_key) . ",'$_value'";
break;
case 'textsize':
case 'captionsize':
case 'closesize':
case 'width':
case 'height':
case 'border':
case 'offsetx':
case 'offsety':
case 'snapx':
case 'snapy':
case 'fixx':
case 'fixy':
case 'padx':
case 'pady':
case 'timeout':
case 'delay':
$append .= ',' . strtoupper($_key) . ",$_value";
break;
case 'sticky':
case 'left':
case 'right':
case 'center':
case 'above':
case 'below':
case 'noclose':
case 'autostatus':
case 'autostatuscap':
case 'fullhtml':
case 'hauto':
case 'vauto':
case 'mouseoff':
case 'followmouse':
case 'closeclick':
case 'wrap':
if ($_value) $append .= ',' . strtoupper($_key);
break;
default:
trigger_error("[popup] unknown parameter $_key", E_USER_WARNING);
}
}
if (empty($text) && !isset($inarray) && empty($function)) {
trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required",E_USER_WARNING);
return false;
}
if (empty($trigger)) { $trigger = "onmouseover"; }
$retval = $trigger . '="return overlib(\''.preg_replace(array("!'!",'!"!',"![\r\n]!"),array("\'","\'",'\r'),$text).'\'';
$retval .= $append . ');"';
if ($trigger == 'onmouseover')
$retval .= ' onmouseout="nd();"';
return $retval;
}
?>

Просмотреть файл

@ -0,0 +1,39 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsFunction
*/
/**
* Smarty {popup_init} function plugin
*
* Type: function<br>
* Name: popup_init<br>
* Purpose: initialize overlib
* @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $params parameters
* @param object $template template object
* @return string
*/
function smarty_function_popup_init($params, $template)
{
$zindex = 1000;
if (!empty($params['zindex'])) {
$zindex = $params['zindex'];
}
if (!empty($params['src'])) {
return '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:'.$zindex.';"></div>' . "\n"
. '<script type="text/javascript" language="JavaScript" src="'.$params['src'].'"></script>' . "\n";
} else {
trigger_error("popup_init: missing src parameter",E_USER_WARNING);
}
}
?>

Просмотреть файл

@ -0,0 +1,37 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty capitalize modifier plugin
*
* Type: modifier<br>
* Name: capitalize<br>
* Purpose: capitalize words in the string
*
* @link
* @author Monte Ohrt <monte at ohrt dot com>
* @param string $
* @return string
*/
function smarty_modifier_capitalize($string, $uc_digits = false)
{
// uppercase with php function ucwords
$upper_string = ucwords($string);
// check for any missed hyphenated words
$upper_string = preg_replace("!(^|[^\p{L}'])([\p{Ll}])!ue", "'\\1'.ucfirst('\\2')", $upper_string);
// check uc_digits case
if (!$uc_digits) {
if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!u", $string, $matches, PREG_OFFSET_CAPTURE)) {
foreach($matches[1] as $match)
$upper_string = substr_replace($upper_string, $match[0], $match[1], strlen($match[0]));
}
}
return $upper_string;
}
?>

Просмотреть файл

@ -0,0 +1,61 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty date_format modifier plugin
*
* Type: modifier<br>
* Name: date_format<br>
* Purpose: format datestamps via strftime<br>
* Input:<br>
* - string: input date string
* - format: strftime format for output
* - default_date: default date if $string is empty
*
* @link http://smarty.php.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param string $
* @param string $
* @param string $
* @return string |void
* @uses smarty_make_timestamp()
*/
function smarty_modifier_date_format($string, $format = SMARTY_RESOURCE_DATE_FORMAT, $default_date = '',$formatter='auto')
{
/**
* Include the {@link shared.make_timestamp.php} plugin
*/
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
if ($string != '') {
$timestamp = smarty_make_timestamp($string);
} elseif ($default_date != '') {
$timestamp = smarty_make_timestamp($default_date);
} else {
return;
}
if($formatter=='strftime'||($formatter=='auto'&&strpos($format,'%')!==false)) {
if (DS == '\\') {
$_win_from = array('%D', '%h', '%n', '%r', '%R', '%t', '%T');
$_win_to = array('%m/%d/%y', '%b', "\n", '%I:%M:%S %p', '%H:%M', "\t", '%H:%M:%S');
if (strpos($format, '%e') !== false) {
$_win_from[] = '%e';
$_win_to[] = sprintf('%\' 2d', date('j', $timestamp));
}
if (strpos($format, '%l') !== false) {
$_win_from[] = '%l';
$_win_to[] = sprintf('%\' 2d', date('h', $timestamp));
}
$format = str_replace($_win_from, $_win_to, $format);
}
return strftime($format, $timestamp);
} else {
return date($format, $timestamp);
}
}
?>

Просмотреть файл

@ -0,0 +1,87 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage Debug
*/
/**
* Smarty debug_print_var modifier plugin
*
* Type: modifier<br>
* Name: debug_print_var<br>
* Purpose: formats variable contents for display in the console
*
* @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php debug_print_var (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param array $ |object
* @param integer $
* @param integer $
* @return string
*/
function smarty_modifier_debug_print_var ($var, $depth = 0, $length = 40)
{
$_replace = array("\n" => '<i>\n</i>',
"\r" => '<i>\r</i>',
"\t" => '<i>\t</i>'
);
switch (gettype($var)) {
case 'array' :
$results = '<b>Array (' . count($var) . ')</b>';
foreach ($var as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
. '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
$depth--;
}
break;
case 'object' :
$object_vars = get_object_vars($var);
$results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
foreach ($object_vars as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
. '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
$depth--;
}
break;
case 'boolean' :
case 'NULL' :
case 'resource' :
if (true === $var) {
$results = 'true';
} elseif (false === $var) {
$results = 'false';
} elseif (null === $var) {
$results = 'null';
} else {
$results = htmlspecialchars((string) $var);
}
$results = '<i>' . $results . '</i>';
break;
case 'integer' :
case 'float' :
$results = htmlspecialchars((string) $var);
break;
case 'string' :
$results = strtr($var, $_replace);
if (strlen($var) > $length) {
$results = substr($var, 0, $length - 3) . '...';
}
$results = htmlspecialchars('"' . $results . '"');
break;
case 'unknown type' :
default :
$results = strtr((string) $var, $_replace);
if (strlen($results) > $length) {
$results = substr($results, 0, $length - 3) . '...';
}
$results = htmlspecialchars($results);
}
return $results;
}
?>

Просмотреть файл

@ -0,0 +1,114 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty escape modifier plugin
*
* Type: modifier<br>
* Name: escape<br>
* Purpose: escape string for output
*
* @link http://smarty.php.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param string $string input string
* @param string $esc_type escape type
* @param string $char_set character set
* @return string escaped input string
*/
function smarty_modifier_escape($string, $esc_type = 'html', $char_set = SMARTY_RESOURCE_CHAR_SET)
{
if (!function_exists('mb_str_replace')) {
// simulate the missing PHP mb_str_replace function
function mb_str_replace($needles, $replacements, $haystack)
{
$rep = (array)$replacements;
foreach ((array)$needles as $key => $needle) {
$replacement = $rep[$key];
$needle_len = mb_strlen($needle);
$replacement_len = mb_strlen($replacement);
$pos = mb_strpos($haystack, $needle, 0);
while ($pos !== false) {
$haystack = mb_substr($haystack, 0, $pos) . $replacement
. mb_substr($haystack, $pos + $needle_len);
$pos = mb_strpos($haystack, $needle, $pos + $replacement_len);
}
}
return $haystack;
}
}
switch ($esc_type) {
case 'html':
return htmlspecialchars($string, ENT_QUOTES, $char_set);
case 'htmlall':
return htmlentities($string, ENT_QUOTES, $char_set);
case 'url':
return rawurlencode($string);
case 'urlpathinfo':
return str_replace('%2F', '/', rawurlencode($string));
case 'quotes':
// escape unescaped single quotes
return preg_replace("%(?<!\\\\)'%", "\\'", $string);
case 'hex':
// escape every character into hex
$return = '';
for ($x = 0; $x < strlen($string); $x++) {
$return .= '%' . bin2hex($string[$x]);
}
return $return;
case 'hexentity':
$return = '';
for ($x = 0; $x < strlen($string); $x++) {
$return .= '&#x' . bin2hex($string[$x]) . ';';
}
return $return;
case 'decentity':
$return = '';
for ($x = 0; $x < strlen($string); $x++) {
$return .= '&#' . ord($string[$x]) . ';';
}
return $return;
case 'javascript':
// escape quotes and backslashes, newlines, etc.
return strtr($string, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', "\r" => '\\r', "\n" => '\\n', '</' => '<\/'));
case 'mail':
// safe way to display e-mail address on a web page
if (function_exists('mb_substr')) {
return mb_str_replace(array('@', '.'), array(' [AT] ', ' [DOT] '), $string);
} else {
return str_replace(array('@', '.'), array(' [AT] ', ' [DOT] '), $string);
}
case 'nonstd':
// escape non-standard chars, such as ms document quotes
$_res = '';
for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
$_ord = ord(substr($string, $_i, 1));
// non-standard char, escape it
if ($_ord >= 126) {
$_res .= '&#' . $_ord . ';';
} else {
$_res .= substr($string, $_i, 1);
}
}
return $_res;
default:
return $string;
}
}
?>

Просмотреть файл

@ -0,0 +1,46 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty regex_replace modifier plugin
*
* Type: modifier<br>
* Name: regex_replace<br>
* Purpose: regular expression search/replace
* @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
* regex_replace (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param string
* @param string|array
* @param string|array
* @return string
*/
function smarty_modifier_regex_replace($string, $search, $replace)
{
if(is_array($search)) {
foreach($search as $idx => $s)
$search[$idx] = _smarty_regex_replace_check($s);
} else {
$search = _smarty_regex_replace_check($search);
}
return preg_replace($search, $replace, $string);
}
function _smarty_regex_replace_check($search)
{
if (($pos = strpos($search,"\0")) !== false)
$search = substr($search,0,$pos);
if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) {
/* remove eval-modifier from $search */
$search = substr($search, 0, -strlen($match[1])) . preg_replace('![e\s]+!', '', $match[1]);
}
return $search;
}
?>

Просмотреть файл

@ -0,0 +1,51 @@
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty replace modifier plugin
*
* Type: modifier<br>
* Name: replace<br>
* Purpose: simple search/replace
*
* @link http://smarty.php.net/manual/en/language.modifier.replace.php replace (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews
* @param string $
* @param string $
* @param string $
* @return string
*/
function smarty_modifier_replace($string, $search, $replace)
{
if (!function_exists('mb_str_replace')) {
// simulate the missing PHP mb_str_replace function
function mb_str_replace($needles, $replacements, $haystack)
{
$rep = (array)$replacements;
foreach ((array)$needles as $key => $needle) {
$replacement = $rep[$key];
$needle_len = mb_strlen($needle);
$replacement_len = mb_strlen($replacement);
$pos = mb_strpos($haystack, $needle, 0);
while ($pos !== false) {
$haystack = mb_substr($haystack, 0, $pos) . $replacement
. mb_substr($haystack, $pos + $needle_len);
$pos = mb_strpos($haystack, $needle, $pos + $replacement_len);
}
}
return $haystack;
}
}
if (function_exists('mb_substr')) {
return mb_str_replace($search, $replace, $string);
} else {
return str_replace($search, $replace, $string);
}
}
?>

Просмотреть файл

@ -0,0 +1,37 @@
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty spacify modifier plugin
*
* Type: modifier<br>
* Name: spacify<br>
* Purpose: add spaces between characters in a string
*
* @link http://smarty.php.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param string $
* @param string $
* @return string
*/
function smarty_modifier_spacify($string, $spacify_char = ' ')
{
// mb_ functions available?
if (function_exists('mb_strlen') && mb_detect_encoding($string, 'UTF-8, ISO-8859-1') === 'UTF-8') {
$strlen = mb_strlen($string);
while ($strlen) {
$array[] = mb_substr($string, 0, 1, "UTF-8");
$string = mb_substr($string, 1, $strlen, "UTF-8");
$strlen = mb_strlen($string);
}
return implode($spacify_char, $array);
} else {
return implode($spacify_char, preg_split('//', $string, -1));
}
}
?>

Просмотреть файл

@ -0,0 +1,67 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty truncate modifier plugin
*
* Type: modifier<br>
* Name: truncate<br>
* Purpose: Truncate a string to a certain length if necessary,
* optionally splitting in the middle of a word, and
* appending the $etc string or inserting $etc into the middle.
*
* @link http://smarty.php.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @param string $string input string
* @param integer $length lenght of truncated text
* @param string $etc end string
* @param boolean $break_words truncate at word boundary
* @param boolean $middle truncate in the middle of text
* @return string truncated string
*/
function smarty_modifier_truncate($string, $length = 80, $etc = '...',
$break_words = false, $middle = false)
{
if ($length == 0)
return '';
if (is_callable('mb_strlen')) {
if (mb_detect_encoding($string, 'UTF-8, ISO-8859-1') === 'UTF-8') {
// $string has utf-8 encoding
if (mb_strlen($string) > $length) {
$length -= min($length, mb_strlen($etc));
if (!$break_words && !$middle) {
$string = preg_replace('/\s+?(\S+)?$/u', '', mb_substr($string, 0, $length + 1));
}
if (!$middle) {
return mb_substr($string, 0, $length) . $etc;
} else {
return mb_substr($string, 0, $length / 2) . $etc . mb_substr($string, - $length / 2);
}
} else {
return $string;
}
}
}
// $string has no utf-8 encoding
if (strlen($string) > $length) {
$length -= min($length, strlen($etc));
if (!$break_words && !$middle) {
$string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length + 1));
}
if (!$middle) {
return substr($string, 0, $length) . $etc;
} else {
return substr($string, 0, $length / 2) . $etc . substr($string, - $length / 2);
}
} else {
return $string;
}
}
?>

Просмотреть файл

@ -0,0 +1,29 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty cat modifier plugin
*
* Type: modifier<br>
* Name: cat<br>
* Date: Feb 24, 2003
* Purpose: catenate a value to a variable
* Input: string to catenate
* Example: {$var|cat:"foo"}
* @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
* (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_cat($params, $compiler)
{
return '('.implode(').(', $params).')';
}
?>

Просмотреть файл

@ -0,0 +1,39 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty count_characters modifier plugin
*
* Type: modifier<br>
* Name: count_characteres<br>
* Purpose: count the number of characters in a text
*
* @link http://smarty.php.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_count_characters($params, $compiler)
{
// mb_ functions available?
if (function_exists('mb_strlen')) {
// count also spaces?
if (isset($params[1]) && $params[1] == 'true') {
return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? mb_strlen(' . $params[0] . ', SMARTY_RESOURCE_CHAR_SET) : strlen(' . $params[0] . '))';
}
return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? preg_match_all(\'#[^\s\pZ]#u\', ' . $params[0] . ', $tmp) : preg_match_all(\'/[^\s]/\',' . $params[0] . ', $tmp))';
} else {
// count also spaces?
if (isset($params[1]) && $params[1] == 'true') {
return 'strlen(' . $params[0] . ')';
}
return 'preg_match_all(\'/[^\s]/\',' . $params[0] . ', $tmp)';
}
}
?>

Просмотреть файл

@ -0,0 +1,27 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty count_paragraphs modifier plugin
*
* Type: modifier<br>
* Name: count_paragraphs<br>
* Purpose: count the number of paragraphs in a text
* @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
* count_paragraphs (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_count_paragraphs($params, $compiler)
{
// count \r or \n characters
return '(preg_match_all(\'#[\r\n]+#\', ' . $params[0] . ', $tmp)+1)';
}
?>

Просмотреть файл

@ -0,0 +1,27 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty count_sentences modifier plugin
*
* Type: modifier<br>
* Name: count_sentences
* Purpose: count the number of sentences in a text
* @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
* count_sentences (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_count_sentences($params, $compiler)
{
// find periods with a word before but not after.
return 'preg_match_all(\'/[^\s]\.(?!\w)/\', ' . $params[0] . ', $tmp)';
}
?>

Просмотреть файл

@ -0,0 +1,31 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty count_words modifier plugin
*
* Type: modifier<br>
* Name: count_words<br>
* Purpose: count the number of words in a text
*
* @link http://smarty.php.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_count_words($params, $compiler)
{
// mb_ functions available?
if (function_exists('mb_strlen')) {
return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? preg_match_all(\'#[\w\pL]+#u\', ' . $params[0] . ', $tmp) : preg_match_all(\'#\w+#\',' . $params[0] . ', $tmp))';
} else {
return 'str_word_count(' . $params[0] . ')';
}
}
?>

Просмотреть файл

@ -0,0 +1,33 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty default modifier plugin
*
* Type: modifier<br>
* Name: default<br>
* Purpose: designate default value for empty variables
*
* @link http://smarty.php.net/manual/en/language.modifier.default.php default (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_default ($params, $compiler)
{
$output = $params[0];
if (!isset($params[1])) {
$params[1] = "''";
}
for ($i = 1, $cnt = count($params); $i < $cnt; $i++) {
$output = '(($tmp = @' . $output . ')===null||$tmp===\'\' ? ' . $params[$i] . ' : $tmp)';
}
return $output;
}
?>

Просмотреть файл

@ -0,0 +1,32 @@
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty indent modifier plugin
*
* Type: modifier<br>
* Name: indent<br>
* Purpose: indent lines of text
* @link http://smarty.php.net/manual/en/language.modifier.indent.php
* indent (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_indent($params, $compiler)
{
if (!isset($params[1])) {
$params[1] = 4;
}
if (!isset($params[2])) {
$params[2] = "' '";
}
return 'preg_replace(\'!^!m\',str_repeat(' . $params[2] . ',' . $params[1] . '),' . $params[0] . ')';
}
?>

Просмотреть файл

@ -0,0 +1,31 @@
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty lower modifier plugin
*
* Type: modifier<br>
* Name: lower<br>
* Purpose: convert string to lowercase
*
* @link http://smarty.php.net/manual/en/language.modifier.lower.php lower (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_lower($params, $compiler)
{
if (function_exists('mb_strtolower')) {
return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? mb_strtolower(' . $params[0] . ',SMARTY_RESOURCE_CHAR_SET) : strtolower(' . $params[0] . '))' ;
} else {
return 'strtolower(' . $params[0] . ')';
}
}
?>

Просмотреть файл

@ -0,0 +1,24 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty noprint modifier plugin
*
* Type: modifier<br>
* Name: noprint<br>
* Purpose: return an empty string
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_noprint($params, $compiler)
{
return "''";
}
?>

Просмотреть файл

@ -0,0 +1,26 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty string_format modifier plugin
*
* Type: modifier<br>
* Name: string_format<br>
* Purpose: format strings via sprintf
*
* @link http://smarty.php.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_string_format($params, $compiler)
{
return 'sprintf(' . $params[1] . ',' . $params[0] . ')';
}
?>

Просмотреть файл

@ -0,0 +1,33 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty strip modifier plugin
*
* Type: modifier<br>
* Name: strip<br>
* Purpose: Replace all repeated spaces, newlines, tabs
* with a single space or supplied replacement string.<br>
* Example: {$var|strip} {$var|strip:"&nbsp;"}
* Date: September 25th, 2002
*
* @link http://smarty.php.net/manual/en/language.modifier.strip.php strip (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_strip($params, $compiler)
{
if (!isset($params[1])) {
$params[1] = "' '";
}
return "preg_replace('!\s+!', {$params[1]},{$params[0]})";
}
?>

Просмотреть файл

@ -0,0 +1,34 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty strip_tags modifier plugin
*
* Type: modifier<br>
* Name: strip_tags<br>
* Purpose: strip html tags from text
*
* @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php strip_tags (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_strip_tags($params, $compiler)
{
if (!isset($params[1])) {
$params[1] = true;
}
if ($params[1] === true) {
return "preg_replace('!<[^>]*?>!', ' ', {$params[0]})";
} else {
return 'strip_tags(' . $params[0] . ')';
}
}
?>

Просмотреть файл

@ -0,0 +1,30 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty upper modifier plugin
*
* Type: modifier<br>
* Name: lower<br>
* Purpose: convert string to uppercase
*
* @link http://smarty.php.net/manual/en/language.modifier.upper.php lower (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_upper($params, $compiler)
{
if (function_exists('mb_strtoupper')) {
return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? mb_strtoupper(' . $params[0] . ',SMARTY_RESOURCE_CHAR_SET) : strtoupper(' . $params[0] . '))' ;
} else {
return 'strtoupper(' . $params[0] . ')';
}
}
?>

Просмотреть файл

@ -0,0 +1,35 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty wordwrap modifier plugin
*
* Type: modifier<br>
* Name: wordwrap<br>
* Purpose: wrap a string of text at a given length
*
* @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual)
* @author Uwe Tews
* @param array $params parameters
* @return string with compiled code
*/
function smarty_modifiercompiler_wordwrap($params, $compiler)
{
if (!isset($params[1])) {
$params[1] = 80;
}
if (!isset($params[2])) {
$params[2] = '"\n"';
}
if (!isset($params[3])) {
$params[3] = 'false';
}
return 'wordwrap(' . $params[0] . ',' . $params[1] . ',' . $params[2] . ',' . $params[3] . ')';
}
?>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше