introduce a filter function at the contact page.
This is done with the help of textcomplete and jsmart.js. There is annoying bug inside. If the screensize is to small, the browser freezes. It is traced back to the "media-body" class (and its css attributes) which we use in the template.
This commit is contained in:
parent
381551569a
commit
17958da201
9 changed files with 3712 additions and 12 deletions
|
|
@ -1596,6 +1596,7 @@ ul.viewcontact_wrapper > li {
|
|||
.contact-wrapper.media {
|
||||
overflow: visible;
|
||||
word-wrap: break-word;
|
||||
margin-top: 0;
|
||||
}
|
||||
/* bootstrap hack for .media */
|
||||
.contact-wrapper.media .media-body {
|
||||
|
|
@ -1710,3 +1711,35 @@ main .nav-tabs>li.active>a:hover {
|
|||
.theme-frio .back-bar .pointer-label {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* textcomplete for contact filtering*/
|
||||
#contact-list ul.dropdown-menu.textcomplete-dropdown.media-list {
|
||||
position: relative !important;
|
||||
top: inherit !important;
|
||||
bottom: inherit !important;
|
||||
left: inherit !important;
|
||||
padding: 0;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
}
|
||||
#contact-list ul.dropdown-menu.textcomplete-dropdown.media-list > li {
|
||||
padding-left: 15px;
|
||||
border-bottom: 1px solid rgba(238, 238, 238, $contentbg_transp);
|
||||
}
|
||||
#contact-list ul.dropdown-menu.textcomplete-dropdown.media-list > li:first-child {
|
||||
display: none;
|
||||
}
|
||||
#contact-list ul.dropdown-menu.textcomplete-dropdown.media-list
|
||||
.textcomplete-item > a {
|
||||
padding: 0 !important;
|
||||
border-left: none;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/* this is a little hack for texcomplete contact filter
|
||||
There are for some reasons empty <a> tags. I don't know why */
|
||||
.textcomplete-item .contact-wrapper a {
|
||||
padding: 0;
|
||||
}
|
||||
|
|
|
|||
3433
frameworks/jsmart/jsmart.js
Normal file
3433
frameworks/jsmart/jsmart.js
Normal file
|
|
@ -0,0 +1,3433 @@
|
|||
/*!
|
||||
* jSmart Javascript template engine
|
||||
* https://github.com/umakantp/jsmart
|
||||
*
|
||||
* Copyright 2011-2015, Max Miroshnikov <miroshnikov at gmail dot com>
|
||||
* Umakant Patil <me at umakantpatil dot.com>
|
||||
* jSmart is licensed under the GNU Lesser General Public License
|
||||
* http://opensource.org/licenses/LGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
merges two or more objects into one
|
||||
shallow copy for objects
|
||||
*/
|
||||
function obMerge(ob1, ob2 /*, ...*/)
|
||||
{
|
||||
for (var i=1; i<arguments.length; ++i)
|
||||
{
|
||||
for (var nm in arguments[i])
|
||||
{
|
||||
ob1[nm] = arguments[i][nm];
|
||||
}
|
||||
}
|
||||
return ob1;
|
||||
}
|
||||
|
||||
/**
|
||||
@return number of own properties in ob
|
||||
*/
|
||||
function countProperties(ob)
|
||||
{
|
||||
var count = 0;
|
||||
for (var nm in ob)
|
||||
{
|
||||
if (ob.hasOwnProperty(nm))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
IE workaround
|
||||
*/
|
||||
function findInArray(a, v)
|
||||
{
|
||||
if (Array.prototype.indexOf) {
|
||||
return a.indexOf(v);
|
||||
}
|
||||
for (var i=0; i < a.length; ++i)
|
||||
{
|
||||
if (a[i] === v)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function evalString(s)
|
||||
{
|
||||
return s.replace(/\\t/,'\t').replace(/\\n/,'\n').replace(/\\(['"\\])/g,'$1');
|
||||
}
|
||||
|
||||
/**
|
||||
@return s trimmed and without quotes
|
||||
*/
|
||||
function trimQuotes(s)
|
||||
{
|
||||
return evalString(s.replace(/^['"](.*)['"]$/,'$1')).replace(/^\s+|\s+$/g,'');
|
||||
}
|
||||
|
||||
/**
|
||||
finds first {tag} in string
|
||||
@param re string with regular expression or an empty string to find any tag
|
||||
@return null or s.match(re) result object where
|
||||
[0] - full tag matched with delimiters (and whitespaces at the begin and the end): { tag }
|
||||
[1] - found part from passed re
|
||||
[index] - position of tag starting { in s
|
||||
*/
|
||||
function findTag(re,s)
|
||||
{
|
||||
var openCount = 0;
|
||||
var offset = 0;
|
||||
var ldelim = jSmart.prototype.left_delimiter;
|
||||
var rdelim = jSmart.prototype.right_delimiter;
|
||||
var skipInWS = jSmart.prototype.auto_literal;
|
||||
|
||||
var reAny = /^\s*(.+)\s*$/i;
|
||||
var reTag = re ? new RegExp('^\\s*('+re+')\\s*$','i') : reAny;
|
||||
|
||||
for (var i=0; i<s.length; ++i)
|
||||
{
|
||||
if (s.substr(i,ldelim.length) == ldelim)
|
||||
{
|
||||
if (skipInWS && i+1 < s.length && s.substr(i+1,1).match(/\s/))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!openCount)
|
||||
{
|
||||
s = s.slice(i);
|
||||
offset += parseInt(i);
|
||||
i = 0;
|
||||
}
|
||||
++openCount;
|
||||
}
|
||||
else if (s.substr(i,rdelim.length) == rdelim)
|
||||
{
|
||||
if (skipInWS && i-1 >= 0 && s.substr(i-1,1).match(/\s/))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!--openCount)
|
||||
{
|
||||
var sTag = s.slice(ldelim.length,i).replace(/[\r\n]/g, ' ');
|
||||
var found = sTag.match(reTag);
|
||||
if (found)
|
||||
{
|
||||
found.index = offset;
|
||||
found[0] = s.slice(0,i+rdelim.length);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
if (openCount < 0) //ignore any number of unmatched right delimiters
|
||||
{
|
||||
openCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findCloseTag(reClose,reOpen,s)
|
||||
{
|
||||
var sInner = '';
|
||||
var closeTag = null;
|
||||
var openTag = null;
|
||||
var findIndex = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (closeTag)
|
||||
{
|
||||
findIndex += closeTag[0].length;
|
||||
}
|
||||
closeTag = findTag(reClose,s);
|
||||
if (!closeTag)
|
||||
{
|
||||
throw new Error('Unclosed {'+reOpen+'}');
|
||||
}
|
||||
sInner += s.slice(0,closeTag.index);
|
||||
findIndex += closeTag.index;
|
||||
s = s.slice(closeTag.index+closeTag[0].length);
|
||||
|
||||
openTag = findTag(reOpen,sInner);
|
||||
if (openTag)
|
||||
{
|
||||
sInner = sInner.slice(openTag.index+openTag[0].length);
|
||||
}
|
||||
}
|
||||
while (openTag);
|
||||
|
||||
closeTag.index = findIndex;
|
||||
return closeTag;
|
||||
}
|
||||
|
||||
function findElseTag(reOpen, reClose, reElse, s)
|
||||
{
|
||||
var offset = 0;
|
||||
for (var elseTag=findTag(reElse,s); elseTag; elseTag=findTag(reElse,s))
|
||||
{
|
||||
var openTag = findTag(reOpen,s);
|
||||
if (!openTag || openTag.index > elseTag.index)
|
||||
{
|
||||
elseTag.index += offset;
|
||||
return elseTag;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = s.slice(openTag.index+openTag[0].length);
|
||||
offset += openTag.index+openTag[0].length;
|
||||
var closeTag = findCloseTag(reClose,reOpen,s);
|
||||
s = s.slice(closeTag.index + closeTag[0].length);
|
||||
offset += closeTag.index + closeTag[0].length;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function execute(code, data)
|
||||
{
|
||||
if (typeof(code) == 'string')
|
||||
{
|
||||
with ({'__code':code})
|
||||
{
|
||||
with (modifiers)
|
||||
{
|
||||
with (data)
|
||||
{
|
||||
try {
|
||||
return eval(__code);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
throw new Error(e.message + ' in \n' + code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute function when we have a object.
|
||||
*
|
||||
* @param object obj Object of the function to be called.
|
||||
* @param array args Arguments to pass to a function.
|
||||
*
|
||||
* @return
|
||||
* @throws Error If function obj does not exists.
|
||||
*/
|
||||
function executeByFuncObject(obj, args) {
|
||||
try {
|
||||
return obj.apply(this, args);
|
||||
} catch (e) {
|
||||
throw new Error(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function assignVar(nm, val, data)
|
||||
{
|
||||
if (nm.match(/\[\]$/)) //ar[] =
|
||||
{
|
||||
data[ nm.replace(/\[\]$/,'') ].push(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[nm] = val;
|
||||
}
|
||||
}
|
||||
|
||||
var buildInFunctions =
|
||||
{
|
||||
expression:
|
||||
{
|
||||
parse: function(s, tree)
|
||||
{
|
||||
var e = parseExpression(s);
|
||||
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'expression',
|
||||
expression: e.tree,
|
||||
params: parseParams(s.slice(e.value.length).replace(/^\s+|\s+$/g,''))
|
||||
});
|
||||
|
||||
return e.tree;
|
||||
|
||||
},
|
||||
process: function(node, data)
|
||||
{
|
||||
var params = getActualParamValues(node.params, data);
|
||||
var res = process([node.expression],data);
|
||||
|
||||
if (findInArray(params, 'nofilter') < 0)
|
||||
{
|
||||
for (var i=0; i<default_modifiers.length; ++i)
|
||||
{
|
||||
var m = default_modifiers[i];
|
||||
m.params.__parsed[0] = {type:'text', data:res};
|
||||
res = process([m],data);
|
||||
}
|
||||
if (escape_html)
|
||||
{
|
||||
res = modifiers.escape(res);
|
||||
}
|
||||
res = applyFilters(varFilters,res);
|
||||
|
||||
if (tpl_modifiers.length) {
|
||||
__t = function(){ return res; }
|
||||
res = process(tpl_modifiers,data);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
|
||||
operator:
|
||||
{
|
||||
process: function(node, data)
|
||||
{
|
||||
var params = getActualParamValues(node.params, data);
|
||||
var arg1 = params[0];
|
||||
|
||||
if (node.optype == 'binary')
|
||||
{
|
||||
var arg2 = params[1];
|
||||
if (node.op == '=')
|
||||
{
|
||||
getVarValue(node.params.__parsed[0], data, arg2);
|
||||
return '';
|
||||
}
|
||||
else if (node.op.match(/(\+=|-=|\*=|\/=|%=)/))
|
||||
{
|
||||
arg1 = getVarValue(node.params.__parsed[0], data);
|
||||
switch (node.op)
|
||||
{
|
||||
case '+=': arg1+=arg2; break;
|
||||
case '-=': arg1-=arg2; break;
|
||||
case '*=': arg1*=arg2; break;
|
||||
case '/=': arg1/=arg2; break;
|
||||
case '%=': arg1%=arg2; break;
|
||||
}
|
||||
return getVarValue(node.params.__parsed[0], data, arg1);
|
||||
}
|
||||
else if (node.op.match(/div/))
|
||||
{
|
||||
return (node.op!='div')^(arg1%arg2==0);
|
||||
}
|
||||
else if (node.op.match(/even/))
|
||||
{
|
||||
return (node.op!='even')^((arg1/arg2)%2==0);
|
||||
}
|
||||
else if (node.op.match(/xor/))
|
||||
{
|
||||
return (arg1||arg2) && !(arg1&&arg2);
|
||||
}
|
||||
|
||||
switch (node.op)
|
||||
{
|
||||
case '==': return arg1==arg2;
|
||||
case '!=': return arg1!=arg2;
|
||||
case '+': return Number(arg1)+Number(arg2);
|
||||
case '-': return Number(arg1)-Number(arg2);
|
||||
case '*': return Number(arg1)*Number(arg2);
|
||||
case '/': return Number(arg1)/Number(arg2);
|
||||
case '%': return Number(arg1)%Number(arg2);
|
||||
case '&&': return arg1&&arg2;
|
||||
case '||': return arg1||arg2;
|
||||
case '<': return arg1<arg2;
|
||||
case '<=': return arg1<=arg2;
|
||||
case '>': return arg1>arg2;
|
||||
case '>=': return arg1>=arg2;
|
||||
case '===': return arg1===arg2;
|
||||
case '!==': return arg1!==arg2;
|
||||
}
|
||||
}
|
||||
else if (node.op == '!')
|
||||
{
|
||||
return !arg1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var isVar = node.params.__parsed[0].type == 'var';
|
||||
if (isVar)
|
||||
{
|
||||
arg1 = getVarValue(node.params.__parsed[0], data);
|
||||
}
|
||||
var v = arg1;
|
||||
if (node.optype == 'pre-unary')
|
||||
{
|
||||
switch (node.op)
|
||||
{
|
||||
case '-': v=-arg1; break;
|
||||
case '++': v=++arg1; break;
|
||||
case '--': v=--arg1; break;
|
||||
}
|
||||
if (isVar)
|
||||
{
|
||||
getVarValue(node.params.__parsed[0], data, arg1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (node.op)
|
||||
{
|
||||
case '++': arg1++; break;
|
||||
case '--': arg1--; break;
|
||||
}
|
||||
getVarValue(node.params.__parsed[0], data, arg1);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
section:
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
var subTree = [];
|
||||
var subTreeElse = [];
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'section',
|
||||
params: params,
|
||||
subTree: subTree,
|
||||
subTreeElse: subTreeElse
|
||||
});
|
||||
|
||||
var findElse = findElseTag('section [^}]+', '\/section', 'sectionelse', content);
|
||||
if (findElse)
|
||||
{
|
||||
parse(content.slice(0,findElse.index),subTree);
|
||||
parse(content.slice(findElse.index+findElse[0].length).replace(/^[\r\n]/,''), subTreeElse);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse(content, subTree);
|
||||
}
|
||||
},
|
||||
|
||||
process: function(node, data)
|
||||
{
|
||||
var params = getActualParamValues(node.params, data);
|
||||
|
||||
var props = {};
|
||||
data.smarty.section[params.__get('name',null,0)] = props;
|
||||
|
||||
var show = params.__get('show',true);
|
||||
props.show = show;
|
||||
if (!show)
|
||||
{
|
||||
return process(node.subTreeElse, data);
|
||||
}
|
||||
|
||||
var from = parseInt(params.__get('start',0));
|
||||
var to = (params.loop instanceof Object) ? countProperties(params.loop) : isNaN(params.loop) ? 0 : parseInt(params.loop);
|
||||
var step = parseInt(params.__get('step',1));
|
||||
var max = parseInt(params.__get('max'));
|
||||
if (isNaN(max))
|
||||
{
|
||||
max = Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
if (from < 0)
|
||||
{
|
||||
from += to;
|
||||
if (from < 0)
|
||||
{
|
||||
from = 0;
|
||||
}
|
||||
}
|
||||
else if (from >= to)
|
||||
{
|
||||
from = to ? to-1 : 0;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var loop = 0;
|
||||
var i = from;
|
||||
for (; i>=0 && i<to && count<max; i+=step,++count)
|
||||
{
|
||||
loop = i;
|
||||
}
|
||||
props.total = count;
|
||||
props.loop = count; //? - because it is so in Smarty
|
||||
|
||||
count = 0;
|
||||
var s = '';
|
||||
for (i=from; i>=0 && i<to && count<max; i+=step,++count)
|
||||
{
|
||||
if (data.smarty['break'])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
props.first = (i==from);
|
||||
props.last = ((i+step)<0 || (i+step)>=to);
|
||||
props.index = i;
|
||||
props.index_prev = i-step;
|
||||
props.index_next = i+step;
|
||||
props.iteration = props.rownum = count+1;
|
||||
|
||||
s += process(node.subTree, data);
|
||||
data.smarty['continue'] = false;
|
||||
}
|
||||
data.smarty['break'] = false;
|
||||
|
||||
if (count)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
return process(node.subTreeElse, data);
|
||||
}
|
||||
},
|
||||
|
||||
setfilter:
|
||||
{
|
||||
type: 'block',
|
||||
parseParams: function(paramStr)
|
||||
{
|
||||
return [parseExpression('__t()|' + paramStr).tree];
|
||||
},
|
||||
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'setfilter',
|
||||
params: params,
|
||||
subTree: parse(content,[])
|
||||
});
|
||||
},
|
||||
|
||||
process: function(node, data)
|
||||
{
|
||||
tpl_modifiers = node.params;
|
||||
var s = process(node.subTree, data);
|
||||
tpl_modifiers = [];
|
||||
return s;
|
||||
}
|
||||
},
|
||||
|
||||
'for':
|
||||
{
|
||||
type: 'block',
|
||||
parseParams: function(paramStr)
|
||||
{
|
||||
var res = paramStr.match(/^\s*\$(\w+)\s*=\s*([^\s]+)\s*to\s*([^\s]+)\s*(?:step\s*([^\s]+))?\s*(.*)$/);
|
||||
if (!res)
|
||||
{
|
||||
throw new Error('Invalid {for} parameters: '+paramStr);
|
||||
}
|
||||
return parseParams("varName='"+res[1]+"' from="+res[2]+" to="+res[3]+" step="+(res[4]?res[4]:'1')+" "+res[5]);
|
||||
},
|
||||
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
var subTree = [];
|
||||
var subTreeElse = [];
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'for',
|
||||
params: params,
|
||||
subTree: subTree,
|
||||
subTreeElse: subTreeElse
|
||||
});
|
||||
|
||||
var findElse = findElseTag('for\\s[^}]+', '\/for', 'forelse', content);
|
||||
if (findElse)
|
||||
{
|
||||
parse(content.slice(0,findElse.index),subTree);
|
||||
parse(content.slice(findElse.index+findElse[0].length), subTreeElse);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse(content, subTree);
|
||||
}
|
||||
},
|
||||
|
||||
process: function(node, data)
|
||||
{
|
||||
var params = getActualParamValues(node.params, data);
|
||||
var from = parseInt(params.__get('from'));
|
||||
var to = parseInt(params.__get('to'));
|
||||
var step = parseInt(params.__get('step'));
|
||||
if (isNaN(step))
|
||||
{
|
||||
step = 1;
|
||||
}
|
||||
var max = parseInt(params.__get('max'));
|
||||
if (isNaN(max))
|
||||
{
|
||||
max = Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var s = '';
|
||||
var total = Math.min( Math.ceil( ((step > 0 ? to-from : from-to)+1) / Math.abs(step) ), max);
|
||||
|
||||
for (var i=parseInt(params.from); count<total; i+=step,++count)
|
||||
{
|
||||
if (data.smarty['break'])
|
||||
{
|
||||
break;
|
||||
}
|
||||
data[params.varName] = i;
|
||||
s += process(node.subTree, data);
|
||||
data.smarty['continue'] = false;
|
||||
}
|
||||
data.smarty['break'] = false;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
s = process(node.subTreeElse, data);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
},
|
||||
|
||||
'if':
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
var subTreeIf = [];
|
||||
var subTreeElse = [];
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'if',
|
||||
params: params,
|
||||
subTreeIf: subTreeIf,
|
||||
subTreeElse: subTreeElse
|
||||
});
|
||||
|
||||
var findElse = findElseTag('if\\s+[^}]+', '\/if', 'else[^}]*', content);
|
||||
if (findElse)
|
||||
{
|
||||
parse(content.slice(0,findElse.index),subTreeIf);
|
||||
|
||||
content = content.slice(findElse.index+findElse[0].length);
|
||||
var findElseIf = findElse[1].match(/^else\s*if(.*)/);
|
||||
if (findElseIf)
|
||||
{
|
||||
buildInFunctions['if'].parse(parseParams(findElseIf[1]), subTreeElse, content.replace(/^\n/,''));
|
||||
}
|
||||
else
|
||||
{
|
||||
parse(content.replace(/^\n/,''), subTreeElse);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parse(content, subTreeIf);
|
||||
}
|
||||
},
|
||||
|
||||
process: function(node, data) {
|
||||
var value = getActualParamValues(node.params,data)[0];
|
||||
// Zero length arrays or empty associative arrays are false in PHP.
|
||||
if (value && !((value instanceof Array && value.length == 0)
|
||||
|| (typeof value == 'object' && isEmptyObject(value)))
|
||||
) {
|
||||
return process(node.subTreeIf, data);
|
||||
} else {
|
||||
return process(node.subTreeElse, data);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
foreach:
|
||||
{
|
||||
type: 'block',
|
||||
parseParams: function(paramStr)
|
||||
{
|
||||
var params = {};
|
||||
var res = paramStr.match(/^\s*([$].+)\s*as\s*[$](\w+)\s*(=>\s*[$](\w+))?\s*$/i);
|
||||
if (res) //Smarty 3.x syntax => Smarty 2.x syntax
|
||||
{
|
||||
paramStr = 'from='+res[1] + ' item='+(res[4]||res[2]);
|
||||
if (res[4])
|
||||
{
|
||||
paramStr += ' key='+res[2];
|
||||
}
|
||||
}
|
||||
return parseParams(paramStr);
|
||||
},
|
||||
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
var subTree = [];
|
||||
var subTreeElse = [];
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'foreach',
|
||||
params: params,
|
||||
subTree: subTree,
|
||||
subTreeElse: subTreeElse
|
||||
});
|
||||
|
||||
var findElse = findElseTag('foreach\\s[^}]+', '\/foreach', 'foreachelse', content);
|
||||
if (findElse)
|
||||
{
|
||||
parse(content.slice(0,findElse.index),subTree);
|
||||
parse(content.slice(findElse.index+findElse[0].length).replace(/^[\r\n]/,''), subTreeElse);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse(content, subTree);
|
||||
}
|
||||
},
|
||||
|
||||
process: function(node, data)
|
||||
{
|
||||
var params = getActualParamValues(node.params, data);
|
||||
var a = params.from;
|
||||
if (!(a instanceof Object))
|
||||
{
|
||||
a = [a];
|
||||
}
|
||||
|
||||
var total = countProperties(a);
|
||||
|
||||
data[params.item+'__total'] = total;
|
||||
if ('name' in params)
|
||||
{
|
||||
data.smarty.foreach[params.name] = {};
|
||||
data.smarty.foreach[params.name].total = total;
|
||||
}
|
||||
|
||||
var s = '';
|
||||
var i=0;
|
||||
for (var key in a)
|
||||
{
|
||||
if (!a.hasOwnProperty(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data.smarty['break'])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
data[params.item+'__key'] = isNaN(key) ? key : parseInt(key);
|
||||
if ('key' in params)
|
||||
{
|
||||
data[params.key] = data[params.item+'__key'];
|
||||
}
|
||||
data[params.item] = a[key];
|
||||
data[params.item+'__index'] = parseInt(i);
|
||||
data[params.item+'__iteration'] = parseInt(i+1);
|
||||
data[params.item+'__first'] = (i===0);
|
||||
data[params.item+'__last'] = (i==total-1);
|
||||
|
||||
if ('name' in params)
|
||||
{
|
||||
data.smarty.foreach[params.name].index = parseInt(i);
|
||||
data.smarty.foreach[params.name].iteration = parseInt(i+1);
|
||||
data.smarty.foreach[params.name].first = (i===0) ? 1 : '';
|
||||
data.smarty.foreach[params.name].last = (i==total-1) ? 1 : '';
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
s += process(node.subTree, data);
|
||||
data.smarty['continue'] = false;
|
||||
}
|
||||
data.smarty['break'] = false;
|
||||
|
||||
data[params.item+'__show'] = (i>0);
|
||||
if (params.name)
|
||||
{
|
||||
data.smarty.foreach[params.name].show = (i>0) ? 1 : '';
|
||||
}
|
||||
if (i>0)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
return process(node.subTreeElse, data);
|
||||
}
|
||||
},
|
||||
|
||||
'function':
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
var subTree = [];
|
||||
plugins[trimQuotes(params.name?params.name:params[0])] =
|
||||
{
|
||||
type: 'function',
|
||||
subTree: subTree,
|
||||
defautParams: params,
|
||||
process: function(params, data)
|
||||
{
|
||||
var defaults = getActualParamValues(this.defautParams,data);
|
||||
delete defaults.name;
|
||||
return process(this.subTree, obMerge({},data,defaults,params));
|
||||
}
|
||||
};
|
||||
parse(content, subTree);
|
||||
}
|
||||
},
|
||||
|
||||
php:
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content) {}
|
||||
},
|
||||
|
||||
'extends':
|
||||
{
|
||||
type: 'function',
|
||||
parse: function(params, tree)
|
||||
{
|
||||
tree.splice(0,tree.length);
|
||||
getTemplate(trimQuotes(params.file?params.file:params[0]),tree);
|
||||
}
|
||||
},
|
||||
|
||||
block:
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'block',
|
||||
params: params
|
||||
});
|
||||
params.append = findInArray(params,'append') >= 0;
|
||||
params.prepend = findInArray(params,'prepend') >= 0;
|
||||
params.hide = findInArray(params,'hide') >= 0;
|
||||
params.hasChild = params.hasParent = false;
|
||||
|
||||
onParseVar = function(nm)
|
||||
{
|
||||
if (nm.match(/^\s*[$]smarty.block.child\s*$/))
|
||||
{
|
||||
params.hasChild = true;
|
||||
}
|
||||
if (nm.match(/^\s*[$]smarty.block.parent\s*$/))
|
||||
{
|
||||
params.hasParent = true;
|
||||
}
|
||||
}
|
||||
var tree = parse(content, []);
|
||||
onParseVar = function(nm) {}
|
||||
|
||||
var blockName = trimQuotes(params.name?params.name:params[0]);
|
||||
if (!(blockName in blocks))
|
||||
{
|
||||
blocks[blockName] = [];
|
||||
}
|
||||
blocks[blockName].push({tree:tree, params:params});
|
||||
},
|
||||
|
||||
process: function(node, data)
|
||||
{
|
||||
data.smarty.block.parent = data.smarty.block.child = '';
|
||||
var blockName = trimQuotes(node.params.name?node.params.name:node.params[0]);
|
||||
this.processBlocks(blocks[blockName], blocks[blockName].length-1, data);
|
||||
return data.smarty.block.child;
|
||||
},
|
||||
|
||||
processBlocks: function(blockAncestry, i, data)
|
||||
{
|
||||
if (!i && blockAncestry[i].params.hide) {
|
||||
data.smarty.block.child = '';
|
||||
return;
|
||||
}
|
||||
var append = true;
|
||||
var prepend = false;
|
||||
for (; i>=0; --i)
|
||||
{
|
||||
if (blockAncestry[i].params.hasParent)
|
||||
{
|
||||
var tmpChild = data.smarty.block.child;
|
||||
data.smarty.block.child = '';
|
||||
this.processBlocks(blockAncestry, i-1, data);
|
||||
data.smarty.block.parent = data.smarty.block.child;
|
||||
data.smarty.block.child = tmpChild;
|
||||
}
|
||||
|
||||
var tmpChild = data.smarty.block.child;
|
||||
var s = process(blockAncestry[i].tree, data);
|
||||
data.smarty.block.child = tmpChild;
|
||||
|
||||
if (blockAncestry[i].params.hasChild)
|
||||
{
|
||||
data.smarty.block.child = s;
|
||||
}
|
||||
else if (append)
|
||||
{
|
||||
data.smarty.block.child = s + data.smarty.block.child;
|
||||
}
|
||||
else if (prepend)
|
||||
{
|
||||
data.smarty.block.child += s;
|
||||
}
|
||||
append = blockAncestry[i].params.append;
|
||||
prepend = blockAncestry[i].params.prepend;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
strip:
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
parse(content.replace(/[ \t]*[\r\n]+[ \t]*/g, ''), tree);
|
||||
}
|
||||
},
|
||||
|
||||
literal:
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
parseText(content, tree);
|
||||
}
|
||||
},
|
||||
|
||||
ldelim:
|
||||
{
|
||||
type: 'function',
|
||||
parse: function(params, tree)
|
||||
{
|
||||
parseText(jSmart.prototype.left_delimiter, tree);
|
||||
}
|
||||
},
|
||||
|
||||
rdelim:
|
||||
{
|
||||
type: 'function',
|
||||
parse: function(params, tree)
|
||||
{
|
||||
parseText(jSmart.prototype.right_delimiter, tree);
|
||||
}
|
||||
},
|
||||
|
||||
'while':
|
||||
{
|
||||
type: 'block',
|
||||
parse: function(params, tree, content)
|
||||
{
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'while',
|
||||
params: params,
|
||||
subTree: parse(content, [])
|
||||
});
|
||||
},
|
||||
|
||||
process: function(node, data)
|
||||
{
|
||||
var s = '';
|
||||
while (getActualParamValues(node.params,data)[0])
|
||||
{
|
||||
if (data.smarty['break'])
|
||||
{
|
||||
break;
|
||||
}
|
||||
s += process(node.subTree, data);
|
||||
data.smarty['continue'] = false;
|
||||
}
|
||||
data.smarty['break'] = false;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var plugins = {};
|
||||
var modifiers = {};
|
||||
var files = {};
|
||||
var blocks = null;
|
||||
var scripts = null;
|
||||
var tpl_modifiers = [];
|
||||
|
||||
function parse(s, tree)
|
||||
{
|
||||
for (var openTag=findTag('',s); openTag; openTag=findTag('',s))
|
||||
{
|
||||
if (openTag.index)
|
||||
{
|
||||
parseText(s.slice(0,openTag.index),tree);
|
||||
}
|
||||
s = s.slice(openTag.index + openTag[0].length);
|
||||
|
||||
var res = openTag[1].match(/^\s*(\w+)(.*)$/);
|
||||
if (res) //function
|
||||
{
|
||||
var nm = res[1];
|
||||
var paramStr = (res.length>2) ? res[2].replace(/^\s+|\s+$/g,'') : '';
|
||||
|
||||
if (nm in buildInFunctions)
|
||||
{
|
||||
var buildIn = buildInFunctions[nm];
|
||||
var params = ('parseParams' in buildIn ? buildIn.parseParams : parseParams)(paramStr);
|
||||
if (buildIn.type == 'block')
|
||||
{
|
||||
s = s.replace(/^\n/,''); //remove new line after block open tag (like in Smarty)
|
||||
var closeTag = findCloseTag('\/'+nm, nm+' +[^}]*', s);
|
||||
buildIn.parse(params, tree, s.slice(0,closeTag.index));
|
||||
s = s.slice(closeTag.index+closeTag[0].length);
|
||||
}
|
||||
else
|
||||
{
|
||||
buildIn.parse(params, tree);
|
||||
if (nm == 'extends')
|
||||
{
|
||||
tree = []; //throw away further parsing except for {block}
|
||||
}
|
||||
}
|
||||
s = s.replace(/^\n/,'');
|
||||
}
|
||||
else if (nm in plugins)
|
||||
{
|
||||
var plugin = plugins[nm];
|
||||
if (plugin.type == 'block')
|
||||
{
|
||||
var closeTag = findCloseTag('\/'+nm, nm+' +[^}]*', s);
|
||||
parsePluginBlock(nm, parseParams(paramStr), tree, s.slice(0,closeTag.index));
|
||||
s = s.slice(closeTag.index+closeTag[0].length);
|
||||
}
|
||||
else if (plugin.type == 'function')
|
||||
{
|
||||
parsePluginFunc(nm, parseParams(paramStr), tree);
|
||||
}
|
||||
if (nm=='append' || nm=='assign' || nm=='capture' || nm=='eval' || nm=='include')
|
||||
{
|
||||
s = s.replace(/^\n/,'');
|
||||
}
|
||||
}
|
||||
else //variable
|
||||
{
|
||||
buildInFunctions.expression.parse(openTag[1],tree);
|
||||
}
|
||||
}
|
||||
else //variable
|
||||
{
|
||||
var node = buildInFunctions.expression.parse(openTag[1],tree);
|
||||
if (node.type=='build-in' && node.name=='operator' && node.op == '=')
|
||||
{
|
||||
s = s.replace(/^\n/,'');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s)
|
||||
{
|
||||
parseText(s, tree);
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
function parseText(text, tree)
|
||||
{
|
||||
if (parseText.parseEmbeddedVars)
|
||||
{
|
||||
var re = /([$][\w@]+)|`([^`]*)`/;
|
||||
for (var found=re.exec(text); found; found=re.exec(text))
|
||||
{
|
||||
tree.push({type: 'text', data: text.slice(0,found.index)});
|
||||
tree.push( parseExpression(found[1] ? found[1] : found[2]).tree );
|
||||
text = text.slice(found.index + found[0].length);
|
||||
}
|
||||
}
|
||||
tree.push({type: 'text', data: text});
|
||||
return tree;
|
||||
}
|
||||
|
||||
function parseFunc(name, params, tree)
|
||||
{
|
||||
params.__parsed.name = parseText(name,[])[0];
|
||||
tree.push({
|
||||
type: 'plugin',
|
||||
name: '__func',
|
||||
params: params
|
||||
});
|
||||
return tree;
|
||||
}
|
||||
|
||||
function parseOperator(op, type, precedence, tree)
|
||||
{
|
||||
tree.push({
|
||||
type: 'build-in',
|
||||
name: 'operator',
|
||||
op: op,
|
||||
optype: type,
|
||||
precedence: precedence,
|
||||
params: {}
|
||||
});
|
||||
}
|
||||
|
||||
function parseVar(s, e, nm)
|
||||
{
|
||||
var rootName = e.token;
|
||||
var parts = [{type:'text', data:nm.replace(/^(\w+)@(key|index|iteration|first|last|show|total)/gi, "$1__$2")}];
|
||||
|
||||
var re = /^(?:\.|\s*->\s*|\[\s*)/;
|
||||
for (var op=s.match(re); op; op=s.match(re))
|
||||
{
|
||||
e.token += op[0];
|
||||
s = s.slice(op[0].length);
|
||||
|
||||
var eProp = {value:'', tree:[]};
|
||||
if (op[0].match(/\[/))
|
||||
{
|
||||
eProp = parseExpression(s);
|
||||
if (eProp)
|
||||
{
|
||||
e.token += eProp.value;
|
||||
parts.push( eProp.tree );
|
||||
s = s.slice(eProp.value.length);
|
||||
}
|
||||
|
||||
var closeOp = s.match(/\s*\]/);
|
||||
if (closeOp)
|
||||
{
|
||||
e.token += closeOp[0];
|
||||
s = s.slice(closeOp[0].length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var parseMod = parseModifiers.stop;
|
||||
parseModifiers.stop = true;
|
||||
if (lookUp(s,eProp))
|
||||
{
|
||||
e.token += eProp.value;
|
||||
var part = eProp.tree[0];
|
||||
if (part.type == 'plugin' && part.name == '__func')
|
||||
{
|
||||
part.hasOwner = true;
|
||||
}
|
||||
parts.push( part );
|
||||
s = s.slice(eProp.value.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
eProp = false;
|
||||
}
|
||||
parseModifiers.stop = parseMod;
|
||||
}
|
||||
|
||||
if (!eProp)
|
||||
{
|
||||
parts.push({type:'text', data:''});
|
||||
}
|
||||
}
|
||||
|
||||
e.tree.push({type: 'var', parts: parts});
|
||||
|
||||
e.value += e.token.substr(rootName.length);
|
||||
|
||||
onParseVar(e.token);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function onParseVar(nm) {}
|
||||
|
||||
|
||||
var tokens =
|
||||
[
|
||||
{
|
||||
re: /^\$([\w@]+)/, //var
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseModifiers(parseVar(s, e, RegExp.$1), e);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(true|false)/i, //bool
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseText(e.token.match(/true/i) ? '1' : '', e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^'([^'\\]*(?:\\.[^'\\]*)*)'/, //single quotes
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseText(evalString(RegExp.$1), e.tree);
|
||||
parseModifiers(s, e);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^"([^"\\]*(?:\\.[^"\\]*)*)"/, //double quotes
|
||||
parse: function(e, s)
|
||||
{
|
||||
var v = evalString(RegExp.$1);
|
||||
var isVar = v.match(tokens[0].re);
|
||||
if (isVar)
|
||||
{
|
||||
var eVar = {token:isVar[0], tree:[]};
|
||||
parseVar(v, eVar, isVar[1]);
|
||||
if (eVar.token.length == v.length)
|
||||
{
|
||||
e.tree.push( eVar.tree[0] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
parseText.parseEmbeddedVars = true;
|
||||
e.tree.push({
|
||||
type: 'plugin',
|
||||
name: '__quoted',
|
||||
params: {__parsed: parse(v,[])}
|
||||
});
|
||||
parseText.parseEmbeddedVars = false;
|
||||
parseModifiers(s, e);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w+)\s*[(]([)]?)/, //func()
|
||||
parse: function(e, s)
|
||||
{
|
||||
var fnm = RegExp.$1;
|
||||
var noArgs = RegExp.$2;
|
||||
var params = parseParams(noArgs?'':s,/^\s*,\s*/);
|
||||
parseFunc(fnm, params, e.tree);
|
||||
e.value += params.toString();
|
||||
parseModifiers(s.slice(params.toString().length), e);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*\(\s*/, //expression in parentheses
|
||||
parse: function(e, s)
|
||||
{
|
||||
var parens = [];
|
||||
e.tree.push(parens);
|
||||
parens.parent = e.tree;
|
||||
e.tree = parens;
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*\)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
if (e.tree.parent) //it may be the end of func() or (expr)
|
||||
{
|
||||
e.tree = e.tree.parent;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(\+\+|--)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
if (e.tree.length && e.tree[e.tree.length-1].type == 'var')
|
||||
{
|
||||
parseOperator(RegExp.$1, 'post-unary', 1, e.tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseOperator(RegExp.$1, 'pre-unary', 1, e.tree);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(===|!==|==|!=)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$1, 'binary', 6, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+(eq|ne|neq)\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
var op = RegExp.$1.replace(/ne(q)?/,'!=').replace(/eq/,'==');
|
||||
parseOperator(op, 'binary', 6, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*!\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator('!', 'pre-unary', 2, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+not\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator('!', 'pre-unary', 2, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(=|\+=|-=|\*=|\/=|%=)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$1, 'binary', 10, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(\*|\/|%)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$1, 'binary', 3, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+mod\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator('%', 'binary', 3, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(\+|-)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
if (!e.tree.length || e.tree[e.tree.length-1].name == 'operator')
|
||||
{
|
||||
parseOperator(RegExp.$1, 'pre-unary', 4, e.tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseOperator(RegExp.$1, 'binary', 4, e.tree);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(<=|>=|<>|<|>)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$1.replace(/<>/,'!='), 'binary', 5, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+(lt|lte|le|gt|gte|ge)\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
var op = RegExp.$1.replace(/lt/,'<').replace(/l(t)?e/,'<=').replace(/gt/,'>').replace(/g(t)?e/,'>=');
|
||||
parseOperator(op, 'binary', 5, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+(is\s+(not\s+)?div\s+by)\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$2?'div_not':'div', 'binary', 7, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+is\s+(not\s+)?(even|odd)(\s+by\s+)?\s*/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
var op = RegExp.$1 ? ((RegExp.$2=='odd')?'even':'even_not') : ((RegExp.$2=='odd')?'even_not':'even');
|
||||
parseOperator(op, 'binary', 7, e.tree);
|
||||
if (!RegExp.$3)
|
||||
{
|
||||
parseText('1', e.tree);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(&&)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$1, 'binary', 8, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*(\|\|)\s*/,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator(RegExp.$1, 'binary', 9, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+and\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator('&&', 'binary', 11, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+xor\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator('xor', 'binary', 12, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s+or\s+/i,
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseOperator('||', 'binary', 13, e.tree);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^#(\w+)#/, //config variable
|
||||
parse: function(e, s)
|
||||
{
|
||||
var eVar = {token:'$smarty',tree:[]};
|
||||
parseVar('.config.'+RegExp.$1, eVar, 'smarty');
|
||||
e.tree.push( eVar.tree[0] );
|
||||
parseModifiers(s, e);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\s*\[\s*/, //array
|
||||
parse: function(e, s)
|
||||
{
|
||||
var params = parseParams(s, /^\s*,\s*/, /^('[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"|\w+)\s*=>\s*/);
|
||||
parsePluginFunc('__array',params,e.tree);
|
||||
e.value += params.toString();
|
||||
var paren = s.slice(params.toString().length).match(/\s*\]/);
|
||||
if (paren)
|
||||
{
|
||||
e.value += paren[0];
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^[\d.]+/, //number
|
||||
parse: function(e, s)
|
||||
{
|
||||
if (e.token.indexOf('.') > -1) {
|
||||
e.token = parseFloat(e.token);
|
||||
} else {
|
||||
e.token = parseInt(e.token, 10);
|
||||
}
|
||||
parseText(e.token, e.tree);
|
||||
parseModifiers(s, e);
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^\w+/, //static
|
||||
parse: function(e, s)
|
||||
{
|
||||
parseText(e.token, e.tree);
|
||||
parseModifiers(s, e);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function parseModifiers(s, e)
|
||||
{
|
||||
if (parseModifiers.stop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var modifier = s.match(/^\|(\w+)/);
|
||||
if (!modifier)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.value += modifier[0];
|
||||
|
||||
var fnm = modifier[1]=='default' ? 'defaultValue' : modifier[1];
|
||||
s = s.slice(modifier[0].length).replace(/^\s+/,'');
|
||||
|
||||
parseModifiers.stop = true;
|
||||
var params = [];
|
||||
for (var colon=s.match(/^\s*:\s*/); colon; colon=s.match(/^\s*:\s*/))
|
||||
{
|
||||
e.value += s.slice(0,colon[0].length);
|
||||
s = s.slice(colon[0].length);
|
||||
|
||||
var param = {value:'', tree:[]};
|
||||
if (lookUp(s, param))
|
||||
{
|
||||
e.value += param.value;
|
||||
params.push(param.tree[0]);
|
||||
s = s.slice(param.value.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseText('',params);
|
||||
}
|
||||
}
|
||||
parseModifiers.stop = false;
|
||||
|
||||
params.unshift(e.tree.pop()); //modifiers have the highest priority
|
||||
e.tree.push(parseFunc(fnm,{__parsed:params},[])[0]);
|
||||
|
||||
parseModifiers(s, e); //modifiers can be combined
|
||||
}
|
||||
|
||||
function lookUp(s,e)
|
||||
{
|
||||
if (!s)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s.substr(0,jSmart.prototype.left_delimiter.length)==jSmart.prototype.left_delimiter)
|
||||
{
|
||||
var tag = findTag('',s);
|
||||
if (tag)
|
||||
{
|
||||
e.token = tag[0];
|
||||
e.value += tag[0];
|
||||
parse(tag[0], e.tree);
|
||||
parseModifiers(s.slice(e.value.length), e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i=0; i<tokens.length; ++i)
|
||||
{
|
||||
if (s.match(tokens[i].re))
|
||||
{
|
||||
e.token = RegExp.lastMatch;
|
||||
e.value += RegExp.lastMatch;
|
||||
tokens[i].parse(e, s.slice(e.token.length));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function bundleOp(i, tree, precedence)
|
||||
{
|
||||
var op = tree[i];
|
||||
if (op.name == 'operator' && op.precedence == precedence && !op.params.__parsed)
|
||||
{
|
||||
if (op.optype == 'binary')
|
||||
{
|
||||
op.params.__parsed = [tree[i-1],tree[i+1]];
|
||||
tree.splice(i-1,3,op);
|
||||
return true;
|
||||
}
|
||||
else if (op.optype == 'post-unary')
|
||||
{
|
||||
op.params.__parsed = [tree[i-1]];
|
||||
tree.splice(i-1,2,op);
|
||||
return true;
|
||||
}
|
||||
|
||||
op.params.__parsed = [tree[i+1]];
|
||||
tree.splice(i,2,op);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function composeExpression(tree)
|
||||
{
|
||||
var i = 0;
|
||||
for (i=0; i<tree.length; ++i)
|
||||
{
|
||||
if (tree[i] instanceof Array)
|
||||
{
|
||||
tree[i] = composeExpression(tree[i])
|
||||
}
|
||||
}
|
||||
|
||||
for (var precedence=1; precedence<14; ++precedence)
|
||||
{
|
||||
if (precedence==2 || precedence==10)
|
||||
{
|
||||
for (i=tree.length; i>0; --i)
|
||||
{
|
||||
i -= bundleOp(i-1, tree, precedence);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<tree.length; ++i)
|
||||
{
|
||||
i -= bundleOp(i, tree, precedence);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tree[0]; //only one node must be left
|
||||
}
|
||||
|
||||
function parseExpression(s)
|
||||
{
|
||||
var e = { value:'', tree:[] };
|
||||
while (lookUp(s.slice(e.value.length), e)){}
|
||||
if (!e.tree.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
e.tree = composeExpression(e.tree);
|
||||
return e;
|
||||
}
|
||||
|
||||
function parseParams(paramsStr, reDelim, reName)
|
||||
{
|
||||
var s = paramsStr.replace(/\n/g,' ').replace(/^\s+|\s+$/g,'');
|
||||
var params = [];
|
||||
params.__parsed = [];
|
||||
var paramsStr = '';
|
||||
|
||||
if (!s)
|
||||
{
|
||||
return params;
|
||||
}
|
||||
|
||||
if (!reDelim)
|
||||
{
|
||||
reDelim = /^\s+/;
|
||||
reName = /^(\w+)\s*=\s*/;
|
||||
}
|
||||
|
||||
while (s)
|
||||
{
|
||||
var nm = null;
|
||||
if (reName)
|
||||
{
|
||||
var foundName = s.match(reName);
|
||||
if (foundName)
|
||||
{
|
||||
nm = trimQuotes(foundName[1]);
|
||||
paramsStr += s.slice(0,foundName[0].length);
|
||||
s = s.slice(foundName[0].length);
|
||||
}
|
||||
}
|
||||
|
||||
var param = parseExpression(s);
|
||||
if (!param)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (nm)
|
||||
{
|
||||
params[nm] = param.value;
|
||||
params.__parsed[nm] = param.tree;
|
||||
}
|
||||
else
|
||||
{
|
||||
params.push(param.value);
|
||||
params.__parsed.push(param.tree);
|
||||
}
|
||||
|
||||
paramsStr += s.slice(0,param.value.length);
|
||||
s = s.slice(param.value.length);
|
||||
|
||||
var foundDelim = s.match(reDelim);
|
||||
if (foundDelim)
|
||||
{
|
||||
paramsStr += s.slice(0,foundDelim[0].length);
|
||||
s = s.slice(foundDelim[0].length);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
params.toString = function() { return paramsStr; }
|
||||
return params;
|
||||
}
|
||||
|
||||
function parsePluginBlock(name, params, tree, content)
|
||||
{
|
||||
tree.push({
|
||||
type: 'plugin',
|
||||
name: name,
|
||||
params: params,
|
||||
subTree: parse(content,[])
|
||||
});
|
||||
}
|
||||
|
||||
function parsePluginFunc(name, params, tree)
|
||||
{
|
||||
tree.push({
|
||||
type: 'plugin',
|
||||
name: name,
|
||||
params: params
|
||||
});
|
||||
}
|
||||
|
||||
function getActualParamValues(params,data)
|
||||
{
|
||||
var actualParams = [];
|
||||
for (var nm in params.__parsed)
|
||||
{
|
||||
if (params.__parsed.hasOwnProperty(nm))
|
||||
{
|
||||
var v = process([params.__parsed[nm]], data);
|
||||
actualParams[nm] = v;
|
||||
}
|
||||
}
|
||||
|
||||
actualParams.__get = function(nm,defVal,id)
|
||||
{
|
||||
if (nm in actualParams && typeof(actualParams[nm]) != 'undefined')
|
||||
{
|
||||
return actualParams[nm];
|
||||
}
|
||||
if (typeof(id)!='undefined' && typeof(actualParams[id]) != 'undefined')
|
||||
{
|
||||
return actualParams[id];
|
||||
}
|
||||
if (defVal === null)
|
||||
{
|
||||
throw new Error("The required attribute '"+nm+"' is missing");
|
||||
}
|
||||
return defVal;
|
||||
};
|
||||
return actualParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean true if object is empty otherwise false.
|
||||
*
|
||||
* @param object hash Object you are testing against.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function isEmptyObject(hash) {
|
||||
for (var i in hash) {
|
||||
if (hash.hasOwnProperty(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getVarValue(node, data, val)
|
||||
{
|
||||
var v = data;
|
||||
var nm = '';
|
||||
for (var i=0; i<node.parts.length; ++i)
|
||||
{
|
||||
var part = node.parts[i];
|
||||
if (part.type == 'plugin' && part.name == '__func' && part.hasOwner)
|
||||
{
|
||||
data.__owner = v;
|
||||
v = process([node.parts[i]],data);
|
||||
delete data.__owner;
|
||||
}
|
||||
else
|
||||
{
|
||||
nm = process([part],data);
|
||||
|
||||
//section name
|
||||
if (nm in data.smarty.section && part.type=='text' && process([node.parts[0]],data)!='smarty')
|
||||
{
|
||||
nm = data.smarty.section[nm].index;
|
||||
}
|
||||
|
||||
//add to array
|
||||
if (!nm && typeof val != 'undefined' && v instanceof Array)
|
||||
{
|
||||
nm = v.length;
|
||||
}
|
||||
|
||||
//set new value
|
||||
if (typeof val != 'undefined' && i==node.parts.length-1)
|
||||
{
|
||||
v[nm] = val;
|
||||
}
|
||||
|
||||
if (typeof v == 'object' && v !== null && nm in v)
|
||||
{
|
||||
v = v[nm];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeof val == 'undefined')
|
||||
{
|
||||
return val;
|
||||
}
|
||||
v[nm] = {};
|
||||
v = v[nm];
|
||||
}
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
function process(tree, data)
|
||||
{
|
||||
var res = '';
|
||||
for (var i=0; i<tree.length; ++i)
|
||||
{
|
||||
var s = '';
|
||||
var node = tree[i];
|
||||
if (node.type == 'text')
|
||||
{
|
||||
s = node.data;
|
||||
}
|
||||
else if (node.type == 'var')
|
||||
{
|
||||
s = getVarValue(node,data);
|
||||
}
|
||||
else if (node.type == 'build-in')
|
||||
{
|
||||
s = buildInFunctions[node.name].process(node,data);
|
||||
}
|
||||
else if (node.type == 'plugin')
|
||||
{
|
||||
var plugin = plugins[node.name];
|
||||
if (plugin.type == 'block')
|
||||
{
|
||||
var repeat = {value:true};
|
||||
plugin.process(getActualParamValues(node.params,data), '', data, repeat);
|
||||
while (repeat.value)
|
||||
{
|
||||
repeat.value = false;
|
||||
s += plugin.process(
|
||||
getActualParamValues(node.params,data),
|
||||
process(node.subTree, data),
|
||||
data,
|
||||
repeat
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (plugin.type == 'function')
|
||||
{
|
||||
s = plugin.process(getActualParamValues(node.params,data), data);
|
||||
}
|
||||
}
|
||||
if (typeof s == 'boolean')
|
||||
{
|
||||
s = s ? '1' : '';
|
||||
}
|
||||
if (tree.length == 1)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
res += s;
|
||||
|
||||
if (data.smarty['continue'] || data.smarty['break'])
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function getTemplate(name, tree, nocache)
|
||||
{
|
||||
if (nocache || !(name in files))
|
||||
{
|
||||
var tpl = jSmart.prototype.getTemplate(name);
|
||||
if (typeof(tpl) != 'string')
|
||||
{
|
||||
throw new Error('No template for '+ name);
|
||||
}
|
||||
parse(applyFilters(jSmart.prototype.filters_global.pre, stripComments(tpl.replace(/\r\n/g,'\n'))), tree);
|
||||
files[name] = tree;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree = files[name];
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
function stripComments(s)
|
||||
{
|
||||
var sRes = '';
|
||||
for (var openTag=s.match(/{\*/); openTag; openTag=s.match(/{\*/))
|
||||
{
|
||||
sRes += s.slice(0,openTag.index);
|
||||
s = s.slice(openTag.index+openTag[0].length);
|
||||
var closeTag = s.match(/\*}/);
|
||||
if (!closeTag)
|
||||
{
|
||||
throw new Error('Unclosed {*');
|
||||
}
|
||||
s = s.slice(closeTag.index+closeTag[0].length);
|
||||
}
|
||||
return sRes + s;
|
||||
}
|
||||
|
||||
function applyFilters(filters, s)
|
||||
{
|
||||
for (var i=0; i<filters.length; ++i)
|
||||
{
|
||||
s = filters[i](s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
jSmart = function(tpl)
|
||||
{
|
||||
this.tree = [];
|
||||
this.tree.blocks = {};
|
||||
this.scripts = {};
|
||||
this.default_modifiers = [];
|
||||
this.filters = {'variable':[], 'post':[]};
|
||||
this.smarty = {
|
||||
'smarty': {
|
||||
block: {},
|
||||
'break': false,
|
||||
capture: {},
|
||||
'continue': false,
|
||||
counter: {},
|
||||
cycle: {},
|
||||
foreach: {},
|
||||
section: {},
|
||||
now: Math.floor( (new Date()).getTime()/1000 ),
|
||||
'const': {},
|
||||
config: {},
|
||||
current_dir: '/',
|
||||
template: '',
|
||||
ldelim: jSmart.prototype.left_delimiter,
|
||||
rdelim: jSmart.prototype.right_delimiter,
|
||||
version: '2.15.0'
|
||||
}
|
||||
};
|
||||
blocks = this.tree.blocks;
|
||||
parse(
|
||||
applyFilters(jSmart.prototype.filters_global.pre, stripComments((new String(tpl?tpl:'')).replace(/\r\n/g,'\n'))),
|
||||
this.tree
|
||||
);
|
||||
};
|
||||
|
||||
jSmart.prototype.fetch = function(data)
|
||||
{
|
||||
blocks = this.tree.blocks;
|
||||
scripts = this.scripts;
|
||||
escape_html = this.escape_html;
|
||||
default_modifiers = jSmart.prototype.default_modifiers_global.concat(this.default_modifiers);
|
||||
this.data = obMerge((typeof data == 'object') ? data : {}, this.smarty);
|
||||
varFilters = jSmart.prototype.filters_global.variable.concat(this.filters.variable);
|
||||
var res = process(this.tree, this.data);
|
||||
if (jSmart.prototype.debugging)
|
||||
{
|
||||
plugins.debug.process([],this.data);
|
||||
}
|
||||
return applyFilters(jSmart.prototype.filters_global.post.concat(this.filters.post), res);
|
||||
};
|
||||
|
||||
jSmart.prototype.escape_html = false;
|
||||
|
||||
/**
|
||||
@param type valid values are 'function', 'block', 'modifier'
|
||||
@param callback func(params,data) or block(params,content,data,repeat)
|
||||
*/
|
||||
jSmart.prototype.registerPlugin = function(type, name, callback)
|
||||
{
|
||||
if (type == 'modifier')
|
||||
{
|
||||
modifiers[name] = callback;
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins[name] = {'type': type, 'process': callback};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@param type valid values are 'pre', 'variable', 'post'
|
||||
@param callback function(textValue) { ... }
|
||||
*/
|
||||
jSmart.prototype.registerFilter = function(type, callback)
|
||||
{
|
||||
(this.tree ? this.filters : jSmart.prototype.filters_global)[type=='output'?'post':type].push(callback);
|
||||
}
|
||||
|
||||
jSmart.prototype.filters_global = {'pre':[],'variable':[],'post':[]};
|
||||
|
||||
jSmart.prototype.configLoad = function(confValues, section, data)
|
||||
{
|
||||
data = data ? data : this.data;
|
||||
var s = confValues.replace(/\r\n/g,'\n').replace(/^\s+|\s+$/g,'');
|
||||
var re = /^\s*(?:\[([^\]]+)\]|(?:(\w+)[ \t]*=[ \t]*("""|'[^'\\\n]*(?:\\.[^'\\\n]*)*'|"[^"\\\n]*(?:\\.[^"\\\n]*)*"|[^\n]*)))/m;
|
||||
var currSect = '';
|
||||
for (var f=s.match(re); f; f=s.match(re))
|
||||
{
|
||||
s = s.slice(f.index+f[0].length);
|
||||
if (f[1])
|
||||
{
|
||||
currSect = f[1];
|
||||
}
|
||||
else if ((!currSect || currSect == section) && currSect.substr(0,1) != '.')
|
||||
{
|
||||
if (f[3] == '"""')
|
||||
{
|
||||
var triple = s.match(/"""/);
|
||||
if (triple)
|
||||
{
|
||||
data.smarty.config[f[2]] = s.slice(0,triple.index);
|
||||
s = s.slice(triple.index + triple[0].length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data.smarty.config[f[2]] = trimQuotes(f[3]);
|
||||
}
|
||||
}
|
||||
var newln = s.match(/\n+/);
|
||||
if (newln)
|
||||
{
|
||||
s = s.slice(newln.index + newln[0].length);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jSmart.prototype.clearConfig = function(varName)
|
||||
{
|
||||
if (varName)
|
||||
{
|
||||
delete this.data.smarty.config[varName];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.data.smarty.config = {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
add modifier to implicitly apply to every variable in a template
|
||||
@param modifiers single string (e.g. "replace:'from':'to'")
|
||||
or array of strings (e.g. ['escape:"htmlall"', "replace:'from':'to'"])
|
||||
*/
|
||||
jSmart.prototype.addDefaultModifier = function(modifiers)
|
||||
{
|
||||
if (!(modifiers instanceof Array))
|
||||
{
|
||||
modifiers = [modifiers];
|
||||
}
|
||||
|
||||
for (var i=0; i<modifiers.length; ++i)
|
||||
{
|
||||
var e = { value:'', tree:[0] };
|
||||
parseModifiers('|'+modifiers[i], e);
|
||||
(this.tree ? this.default_modifiers : this.default_modifiers_global).push( e.tree[0] );
|
||||
}
|
||||
}
|
||||
|
||||
jSmart.prototype.default_modifiers_global = [];
|
||||
|
||||
/**
|
||||
override this function
|
||||
@param name value of 'file' parameter in {include} and {extends}
|
||||
@return template text
|
||||
*/
|
||||
jSmart.prototype.getTemplate = function(name)
|
||||
{
|
||||
throw new Error('No template for ' + name);
|
||||
}
|
||||
|
||||
/**
|
||||
override this function
|
||||
@param name value of 'file' parameter in {fetch}
|
||||
@return file content
|
||||
*/
|
||||
jSmart.prototype.getFile = function(name)
|
||||
{
|
||||
throw new Error('No file for ' + name);
|
||||
}
|
||||
|
||||
/**
|
||||
override this function
|
||||
@param name value of 'file' parameter in {include_php} and {include_javascript}
|
||||
or value of 'script' parameter in {insert}
|
||||
@return Javascript script
|
||||
*/
|
||||
jSmart.prototype.getJavascript = function(name)
|
||||
{
|
||||
throw new Error('No Javascript for ' + name);
|
||||
}
|
||||
|
||||
/**
|
||||
override this function
|
||||
@param name value of 'file' parameter in {config_load}
|
||||
@return config file content
|
||||
*/
|
||||
jSmart.prototype.getConfig = function(name)
|
||||
{
|
||||
throw new Error('No config for ' + name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
whether to skip tags in open brace { followed by white space(s) and close brace } with white space(s) before
|
||||
*/
|
||||
jSmart.prototype.auto_literal = true;
|
||||
|
||||
jSmart.prototype.left_delimiter = '{';
|
||||
jSmart.prototype.right_delimiter = '}';
|
||||
|
||||
/** enables the debugging console */
|
||||
jSmart.prototype.debugging = false;
|
||||
|
||||
|
||||
jSmart.prototype.PHPJS = function(fnm, modifier)
|
||||
{
|
||||
if (eval('typeof '+fnm) == 'function')
|
||||
{
|
||||
return (typeof window == 'object') ? window : global;
|
||||
}
|
||||
else if (typeof(PHP_JS) == 'function')
|
||||
{
|
||||
return new PHP_JS();
|
||||
}
|
||||
throw new Error("Modifier '" + modifier + "' uses JavaScript port of PHP function '" + fnm + "'. You can find one at http://phpjs.org");
|
||||
}
|
||||
|
||||
jSmart.prototype.makeTimeStamp = function(s)
|
||||
{
|
||||
if (!s)
|
||||
{
|
||||
return Math.floor( (new Date()).getTime()/1000 );
|
||||
}
|
||||
if (isNaN(s))
|
||||
{
|
||||
var tm = jSmart.prototype.PHPJS('strtotime','date_format').strtotime(s);
|
||||
if (tm == -1 || tm === false) {
|
||||
return Math.floor( (new Date()).getTime()/1000 );
|
||||
}
|
||||
return tm;
|
||||
}
|
||||
s = new String(s);
|
||||
if (s.length == 14) //mysql timestamp format of YYYYMMDDHHMMSS
|
||||
{
|
||||
return Math.floor( (new Date(s.substr(0,4),s.substr(4,2)-1,s.substr(6,2),s.substr(8,2),s.substr(10,2)).getTime()/1000 ) );
|
||||
}
|
||||
return parseInt(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
register custom functions
|
||||
*/
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'__array',
|
||||
function(params, data)
|
||||
{
|
||||
var a = [];
|
||||
for (var nm in params)
|
||||
{
|
||||
if (params.hasOwnProperty(nm) && params[nm] && typeof params[nm] != 'function')
|
||||
{
|
||||
a[nm] = params[nm];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'__func',
|
||||
function(params, data) {
|
||||
var paramNames = [], paramValues = {}, paramData = [];
|
||||
for (var i=0; i<params.length; ++i) {
|
||||
paramNames.push(params.name+'__p'+i);
|
||||
paramData.push(params[i]);
|
||||
paramValues[params.name+'__p'+i] = params[i];
|
||||
}
|
||||
var fname, mergedParams = obMerge({}, data, paramValues);
|
||||
if (('__owner' in data && params.name in data.__owner)) {
|
||||
fname = '__owner.'+params.name;
|
||||
return execute(fname + '(' + paramNames.join(',') + ')', mergedParams);
|
||||
} else if (modifiers.hasOwnProperty(params.name)) {
|
||||
fname = modifiers[params.name]
|
||||
return executeByFuncObject(fname, paramData, mergedParams);
|
||||
} else {
|
||||
fname = params.name;
|
||||
return execute(fname + '(' + paramNames.join(',') + ')', mergedParams);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'__quoted',
|
||||
function(params, data)
|
||||
{
|
||||
return params.join('');
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'append',
|
||||
function(params, data)
|
||||
{
|
||||
var varName = params.__get('var',null,0);
|
||||
if (!(varName in data) || !(data[varName] instanceof Array))
|
||||
{
|
||||
data[varName] = [];
|
||||
}
|
||||
var index = params.__get('index',false);
|
||||
var val = params.__get('value',null,1);
|
||||
if (index === false)
|
||||
{
|
||||
data[varName].push(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[varName][index] = val;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'assign',
|
||||
function(params, data)
|
||||
{
|
||||
assignVar(params.__get('var',null,0), params.__get('value',null,1), data);
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'break',
|
||||
function(params, data)
|
||||
{
|
||||
data.smarty['break'] = true;
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'call',
|
||||
function(params, data)
|
||||
{
|
||||
var fname = params.__get('name',null,0);
|
||||
delete params.name;
|
||||
var assignTo = params.__get('assign',false);
|
||||
delete params.assign;
|
||||
var s = plugins[fname].process(params, data);
|
||||
if (assignTo)
|
||||
{
|
||||
assignVar(assignTo, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'block',
|
||||
'capture',
|
||||
function(params, content, data, repeat)
|
||||
{
|
||||
if (content)
|
||||
{
|
||||
content = content.replace(/^\n/,'');
|
||||
data.smarty.capture[params.__get('name','default',0)] = content;
|
||||
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, content, data);
|
||||
}
|
||||
|
||||
var append = params.__get('append',false);
|
||||
if (append)
|
||||
{
|
||||
if (append in data)
|
||||
{
|
||||
if (data[append] instanceof Array)
|
||||
{
|
||||
data[append].push(content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data[append] = [content];
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'continue',
|
||||
function(params, data)
|
||||
{
|
||||
data.smarty['continue'] = true;
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'counter',
|
||||
function(params, data)
|
||||
{
|
||||
var name = params.__get('name','default');
|
||||
if (name in data.smarty.counter)
|
||||
{
|
||||
var counter = data.smarty.counter[name];
|
||||
if ('start' in params)
|
||||
{
|
||||
counter.value = parseInt(params['start']);
|
||||
}
|
||||
else
|
||||
{
|
||||
counter.value = parseInt(counter.value);
|
||||
counter.skip = parseInt(counter.skip);
|
||||
if ('down' == counter.direction)
|
||||
{
|
||||
counter.value -= counter.skip;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter.value += counter.skip;
|
||||
}
|
||||
}
|
||||
counter.skip = params.__get('skip',counter.skip);
|
||||
counter.direction = params.__get('direction',counter.direction);
|
||||
counter.assign = params.__get('assign',counter.assign);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.smarty.counter[name] = {
|
||||
value: parseInt(params.__get('start',1)),
|
||||
skip: parseInt(params.__get('skip',1)),
|
||||
direction: params.__get('direction','up'),
|
||||
assign: params.__get('assign',false)
|
||||
};
|
||||
}
|
||||
|
||||
if (data.smarty.counter[name].assign)
|
||||
{
|
||||
data[data.smarty.counter[name].assign] = data.smarty.counter[name].value;
|
||||
return '';
|
||||
}
|
||||
|
||||
if (params.__get('print',true))
|
||||
{
|
||||
return data.smarty.counter[name].value;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'cycle',
|
||||
function(params, data)
|
||||
{
|
||||
var name = params.__get('name','default');
|
||||
var reset = params.__get('reset',false);
|
||||
if (!(name in data.smarty.cycle))
|
||||
{
|
||||
data.smarty.cycle[name] = {arr: [''], delimiter: params.__get('delimiter',','), index: 0};
|
||||
reset = true;
|
||||
}
|
||||
|
||||
if (params.__get('delimiter',false))
|
||||
{
|
||||
data.smarty.cycle[name].delimiter = params.delimiter;
|
||||
}
|
||||
var values = params.__get('values',false);
|
||||
if (values)
|
||||
{
|
||||
var arr = [];
|
||||
if (values instanceof Object)
|
||||
{
|
||||
for (nm in values)
|
||||
{
|
||||
arr.push(values[nm]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arr = values.split(data.smarty.cycle[name].delimiter);
|
||||
}
|
||||
|
||||
if (arr.length != data.smarty.cycle[name].arr.length || arr[0] != data.smarty.cycle[name].arr[0])
|
||||
{
|
||||
data.smarty.cycle[name].arr = arr;
|
||||
data.smarty.cycle[name].index = 0;
|
||||
reset = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.__get('advance','true'))
|
||||
{
|
||||
data.smarty.cycle[name].index += 1;
|
||||
}
|
||||
if (data.smarty.cycle[name].index >= data.smarty.cycle[name].arr.length || reset)
|
||||
{
|
||||
data.smarty.cycle[name].index = 0;
|
||||
}
|
||||
|
||||
if (params.__get('assign',false))
|
||||
{
|
||||
assignVar(params.assign, data.smarty.cycle[name].arr[ data.smarty.cycle[name].index ], data);
|
||||
return '';
|
||||
}
|
||||
|
||||
if (params.__get('print',true))
|
||||
{
|
||||
return data.smarty.cycle[name].arr[ data.smarty.cycle[name].index ];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.print_r = function(v,indent)
|
||||
{
|
||||
if (v instanceof Object)
|
||||
{
|
||||
var s = ((v instanceof Array) ? 'Array['+v.length+']' : 'Object') + '<br>';
|
||||
for (var nm in v)
|
||||
{
|
||||
if (v.hasOwnProperty(nm))
|
||||
{
|
||||
s += indent + ' <strong>' + nm + '</strong> : ' + jSmart.prototype.print_r(v[nm],indent+' ') + '<br>';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'debug',
|
||||
function(params, data)
|
||||
{
|
||||
if (typeof dbgWnd != 'undefined')
|
||||
{
|
||||
dbgWnd.close();
|
||||
}
|
||||
dbgWnd = window.open('','','width=680,height=600,resizable,scrollbars=yes');
|
||||
var sVars = '';
|
||||
var i=0;
|
||||
for (var nm in data)
|
||||
{
|
||||
sVars += '<tr class=' + (++i%2?'odd':'even') + '><td><strong>' + nm + '</strong></td><td>' + jSmart.prototype.print_r(data[nm],'') + '</td></tr>';
|
||||
}
|
||||
dbgWnd.document.write(" \
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'> \
|
||||
<head> \
|
||||
<title>jSmart Debug Console</title> \
|
||||
<style type='text/css'> \
|
||||
table {width: 100%;} \
|
||||
td {vertical-align:top;width: 50%;} \
|
||||
.even td {background-color: #fafafa;} \
|
||||
</style> \
|
||||
</head> \
|
||||
<body> \
|
||||
<h1>jSmart Debug Console</h1> \
|
||||
<h2>assigned template variables</h2> \
|
||||
<table>" + sVars + "</table> \
|
||||
</body> \
|
||||
</html> \
|
||||
");
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'eval',
|
||||
function(params, data)
|
||||
{
|
||||
var tree = [];
|
||||
parse(params.__get('var','',0), tree);
|
||||
var s = process(tree, data);
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'fetch',
|
||||
function(params, data)
|
||||
{
|
||||
var s = jSmart.prototype.getFile(params.__get('file',null,0));
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'html_checkboxes',
|
||||
function (params, data) {
|
||||
var type = params.__get('type','checkbox'),
|
||||
name = params.__get('name',type),
|
||||
realName = params.__get('name',type),
|
||||
values = params.__get('values',params.options),
|
||||
output = params.__get('options',[]),
|
||||
useName = ('options' in params),
|
||||
selected = params.__get('selected',false),
|
||||
separator = params.__get('separator',''),
|
||||
labels = Boolean(params.__get('labels',true)),
|
||||
label_ids = Boolean(params.__get('label_ids',false)),
|
||||
p,
|
||||
res = [],
|
||||
i = 0,
|
||||
s = '',
|
||||
value,
|
||||
id;
|
||||
|
||||
if (type == 'checkbox') {
|
||||
name += '[]';
|
||||
}
|
||||
if (!useName) {
|
||||
for (p in params.output) {
|
||||
output.push(params.output[p]);
|
||||
}
|
||||
}
|
||||
|
||||
for (p in values) {
|
||||
if (values.hasOwnProperty(p)) {
|
||||
value = (useName ? p : values[p]);
|
||||
id = realName + '_' + value;
|
||||
s = (labels ? ( label_ids ? '<label for="'+id+'">' : '<label>') : '');
|
||||
|
||||
s += '<input type="' + type + '" name="' + name + '" value="' + value + '" ';
|
||||
if (label_ids) {
|
||||
s += 'id="'+id+'" ';
|
||||
}
|
||||
if (selected == (useName ? p : values[p])) {
|
||||
s += 'checked="checked" ';
|
||||
}
|
||||
s += '/>' + output[useName?p:i++];
|
||||
s += (labels ? '</label>' : '');
|
||||
s += separator;
|
||||
res.push(s);
|
||||
}
|
||||
}
|
||||
if ('assign' in params) {
|
||||
assignVar(params.assign, res, data);
|
||||
return '';
|
||||
}
|
||||
return res.join('\n');
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'html_image',
|
||||
function (params, data) {
|
||||
var url = params.__get('file', null),
|
||||
width = params.__get('width', false),
|
||||
height = params.__get('height', false),
|
||||
alt = params.__get('alt', ''),
|
||||
href = params.__get('href', params.__get('link', false)),
|
||||
path_prefix = params.__get('path_prefix', ''),
|
||||
paramNames = {file:1, width:1, height:1, alt:1, href:1, basedir:1, path_prefix:1, link:1},
|
||||
s = '<img src="' + path_prefix + url + '"' + ' alt="'+alt+'"' + (width ? ' width="'+width+'"':'') + (height ? ' height="'+height+'"':''),
|
||||
p;
|
||||
|
||||
for (p in params) {
|
||||
if (params.hasOwnProperty(p) && typeof(params[p]) == 'string') {
|
||||
if (!(p in paramNames)) {
|
||||
s += ' ' + p + '="' + params[p] + '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
s += ' />';
|
||||
return href ? '<a href="'+href+'">'+s+'</a>' : s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'html_options',
|
||||
function(params, data)
|
||||
{
|
||||
var values = params.__get('values',params.options);
|
||||
var output = params.__get('options',[]);
|
||||
var useName = ('options' in params);
|
||||
var p;
|
||||
if (!useName)
|
||||
{
|
||||
for (p in params.output)
|
||||
{
|
||||
output.push(params.output[p]);
|
||||
}
|
||||
}
|
||||
var selected = params.__get('selected',false);
|
||||
|
||||
var res = [];
|
||||
var s = '';
|
||||
var i = 0;
|
||||
for (p in values)
|
||||
{
|
||||
if (values.hasOwnProperty(p))
|
||||
{
|
||||
s = '<option value="' + (useName ? p : values[p]) + '"';
|
||||
if (selected == (useName ? p : values[p]))
|
||||
{
|
||||
s += ' selected="selected"';
|
||||
}
|
||||
s += '>' + output[useName ? p : i++] + '</option>';
|
||||
res.push(s);
|
||||
}
|
||||
}
|
||||
var name = params.__get('name',false);
|
||||
return (name ? ('<select name="' + name + '">\n' + res.join('\n') + '\n</select>') : res.join('\n')) + '\n';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'html_radios',
|
||||
function(params, data)
|
||||
{
|
||||
params.type = 'radio';
|
||||
return plugins.html_checkboxes.process(params,data);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'html_select_date',
|
||||
function(params, data)
|
||||
{
|
||||
var prefix = params.__get('prefix','Date_');
|
||||
var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
||||
|
||||
var s = '';
|
||||
s += '<select name="'+prefix+'Month">\n';
|
||||
var i=0;
|
||||
for (i=0; i<months.length; ++i)
|
||||
{
|
||||
s += '<option value="' + i + '">' + months[i] + '</option>\n';
|
||||
}
|
||||
s += '</select>\n'
|
||||
|
||||
s += '<select name="'+prefix+'Day">\n';
|
||||
for (i=0; i<31; ++i)
|
||||
{
|
||||
s += '<option value="' + i + '">' + i + '</option>\n';
|
||||
}
|
||||
s += '</select>\n'
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'html_table',
|
||||
function(params, data)
|
||||
{
|
||||
var loop = [];
|
||||
var p;
|
||||
if (params.loop instanceof Array)
|
||||
{
|
||||
loop = params.loop
|
||||
}
|
||||
else
|
||||
{
|
||||
for (p in params.loop)
|
||||
{
|
||||
if (params.loop.hasOwnProperty(p))
|
||||
{
|
||||
loop.push( params.loop[p] );
|
||||
}
|
||||
}
|
||||
}
|
||||
var rows = params.__get('rows',false);
|
||||
var cols = params.__get('cols',false);
|
||||
if (!cols)
|
||||
{
|
||||
cols = rows ? Math.ceil(loop.length/rows) : 3;
|
||||
}
|
||||
var colNames = [];
|
||||
if (isNaN(cols))
|
||||
{
|
||||
if (typeof cols == 'object')
|
||||
{
|
||||
for (p in cols)
|
||||
{
|
||||
if (cols.hasOwnProperty(p))
|
||||
{
|
||||
colNames.push(cols[p]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colNames = cols.split(/\s*,\s*/);
|
||||
}
|
||||
cols = colNames.length;
|
||||
}
|
||||
rows = rows ? rows : Math.ceil(loop.length/cols);
|
||||
|
||||
var inner = params.__get('inner','cols');
|
||||
var caption = params.__get('caption','');
|
||||
var table_attr = params.__get('table_attr','border="1"');
|
||||
var th_attr = params.__get('th_attr',false);
|
||||
if (th_attr && typeof th_attr != 'object')
|
||||
{
|
||||
th_attr = [th_attr];
|
||||
}
|
||||
var tr_attr = params.__get('tr_attr',false);
|
||||
if (tr_attr && typeof tr_attr != 'object')
|
||||
{
|
||||
tr_attr = [tr_attr];
|
||||
}
|
||||
var td_attr = params.__get('td_attr',false);
|
||||
if (td_attr && typeof td_attr != 'object')
|
||||
{
|
||||
td_attr = [td_attr];
|
||||
}
|
||||
var trailpad = params.__get('trailpad',' ');
|
||||
var hdir = params.__get('hdir','right');
|
||||
var vdir = params.__get('vdir','down');
|
||||
|
||||
var s = '';
|
||||
for (var row=0; row<rows; ++row)
|
||||
{
|
||||
s += '<tr' + (tr_attr ? ' '+tr_attr[row%tr_attr.length] : '') + '>\n';
|
||||
for (var col=0; col<cols; ++col)
|
||||
{
|
||||
var idx = (inner=='cols') ? ((vdir=='down'?row:rows-1-row) * cols + (hdir=='right'?col:cols-1-col)) : ((hdir=='right'?col:cols-1-col) * rows + (vdir=='down'?row:rows-1-row));
|
||||
|
||||
s += '<td' + (td_attr ? ' '+td_attr[col%td_attr.length] : '') + '>' + (idx < loop.length ? loop[idx] : trailpad) + '</td>\n';
|
||||
}
|
||||
s += '</tr>\n';
|
||||
}
|
||||
|
||||
var sHead = '';
|
||||
if (colNames.length)
|
||||
{
|
||||
sHead = '\n<thead><tr>';
|
||||
for (var i=0; i<colNames.length; ++i)
|
||||
{
|
||||
sHead += '\n<th' + (th_attr ? ' '+th_attr[i%th_attr.length] : '') + '>' + colNames[hdir=='right'?i:colNames.length-1-i] + '</th>';
|
||||
}
|
||||
sHead += '\n</tr></thead>';
|
||||
}
|
||||
|
||||
return '<table ' + table_attr + '>' + (caption?'\n<caption>'+caption+'</caption>':'') + sHead + '\n<tbody>\n' + s + '</tbody>\n</table>\n';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'include',
|
||||
function(params, data)
|
||||
{
|
||||
var file = params.__get('file',null,0);
|
||||
var incData = obMerge({},data,params);
|
||||
incData.smarty.template = file;
|
||||
var s = process(getTemplate(file,[],findInArray(params,'nocache')>=0), incData);
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'include_javascript',
|
||||
function(params, data)
|
||||
{
|
||||
var file = params.__get('file',null,0);
|
||||
if (params.__get('once',true) && file in scripts)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
scripts[file] = true;
|
||||
var s = execute(jSmart.prototype.getJavascript(file), {'$this':data});
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'include_php',
|
||||
function(params, data)
|
||||
{
|
||||
return plugins['include_javascript'].process(params,data);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'insert',
|
||||
function(params, data)
|
||||
{
|
||||
var fparams = {};
|
||||
for (var nm in params)
|
||||
{
|
||||
if (params.hasOwnProperty(nm) && isNaN(nm) && params[nm] && typeof params[nm] == 'string' && nm != 'name' && nm != 'assign' && nm != 'script')
|
||||
{
|
||||
fparams[nm] = params[nm];
|
||||
}
|
||||
}
|
||||
var prefix = 'insert_';
|
||||
if ('script' in params)
|
||||
{
|
||||
eval(jSmart.prototype.getJavascript(params.script));
|
||||
prefix = 'smarty_insert_';
|
||||
}
|
||||
var func = eval(prefix+params.__get('name',null,0));
|
||||
var s = func(fparams, data);
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'block',
|
||||
'javascript',
|
||||
function(params, content, data, repeat)
|
||||
{
|
||||
data['$this'] = data;
|
||||
execute(content,data);
|
||||
delete data['$this'];
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'config_load',
|
||||
function(params, data)
|
||||
{
|
||||
jSmart.prototype.configLoad(jSmart.prototype.getConfig(params.__get('file',null,0)), params.__get('section','',1), data);
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'mailto',
|
||||
function(params, data)
|
||||
{
|
||||
var address = params.__get('address',null);
|
||||
var encode = params.__get('encode','none');
|
||||
var text = params.__get('text',address);
|
||||
var cc = jSmart.prototype.PHPJS('rawurlencode','mailto').rawurlencode(params.__get('cc','')).replace('%40','@');
|
||||
var bcc = jSmart.prototype.PHPJS('rawurlencode','mailto').rawurlencode(params.__get('bcc','')).replace('%40','@');
|
||||
var followupto = jSmart.prototype.PHPJS('rawurlencode','mailto').rawurlencode(params.__get('followupto','')).replace('%40','@');
|
||||
var subject = jSmart.prototype.PHPJS('rawurlencode','mailto').rawurlencode( params.__get('subject','') );
|
||||
var newsgroups = jSmart.prototype.PHPJS('rawurlencode','mailto').rawurlencode(params.__get('newsgroups',''));
|
||||
var extra = params.__get('extra','');
|
||||
|
||||
address += (cc?'?cc='+cc:'');
|
||||
address += (bcc?(cc?'&':'?')+'bcc='+bcc:'');
|
||||
address += (subject ? ((cc||bcc)?'&':'?') + 'subject='+subject : '');
|
||||
address += (newsgroups ? ((cc||bcc||subject)?'&':'?') + 'newsgroups='+newsgroups : '');
|
||||
address += (followupto ? ((cc||bcc||subject||newsgroups)?'&':'?') + 'followupto='+followupto : '');
|
||||
|
||||
s = '<a href="mailto:' + address + '" ' + extra + '>' + text + '</a>';
|
||||
|
||||
if (encode == 'javascript')
|
||||
{
|
||||
s = "document.write('" + s + "');";
|
||||
var sEncoded = '';
|
||||
for (var i=0; i<s.length; ++i)
|
||||
{
|
||||
sEncoded += '%' + jSmart.prototype.PHPJS('bin2hex','mailto').bin2hex(s.substr(i,1));
|
||||
}
|
||||
return '<script type="text/javascript">eval(unescape(\'' + sEncoded + "'))</script>";
|
||||
}
|
||||
else if (encode == 'javascript_charcode')
|
||||
{
|
||||
var codes = [];
|
||||
for (var i=0; i<s.length; ++i)
|
||||
{
|
||||
codes.push(jSmart.prototype.PHPJS('ord','mailto').ord(s.substr(i,1)));
|
||||
}
|
||||
return '<script type="text/javascript" language="javascript">\n<!--\n{document.write(String.fromCharCode('
|
||||
+ codes.join(',') + '))}\n//-->\n</script>\n';
|
||||
}
|
||||
else if (encode == 'hex')
|
||||
{
|
||||
if (address.match(/^.+\?.+$/))
|
||||
{
|
||||
throw new Error('mailto: hex encoding does not work with extra attributes. Try javascript.');
|
||||
}
|
||||
var aEncoded = '';
|
||||
for (var i=0; i<address.length; ++i)
|
||||
{
|
||||
if (address.substr(i,1).match(/\w/))
|
||||
{
|
||||
aEncoded += '%' + jSmart.prototype.PHPJS('bin2hex','mailto').bin2hex(address.substr(i,1));
|
||||
}
|
||||
else
|
||||
{
|
||||
aEncoded += address.substr(i,1);
|
||||
}
|
||||
}
|
||||
var tEncoded = '';
|
||||
for (var i=0; i<text.length; ++i)
|
||||
{
|
||||
tEncoded += '&#x' + jSmart.prototype.PHPJS('bin2hex','mailto').bin2hex(text.substr(i,1)) + ';';
|
||||
}
|
||||
return '<a href="mailto:' + aEncoded + '" ' + extra + '>' + tEncoded + '</a>';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'function',
|
||||
'math',
|
||||
function(params, data)
|
||||
{
|
||||
with (Math)
|
||||
{
|
||||
with (params)
|
||||
{
|
||||
var res = eval(params.__get('equation',null).replace(/pi\(\s*\)/g,'PI'));
|
||||
}
|
||||
}
|
||||
|
||||
if ('format' in params)
|
||||
{
|
||||
res = jSmart.prototype.PHPJS('sprintf','math').sprintf(params.format,res);
|
||||
}
|
||||
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, res, data);
|
||||
return '';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'block',
|
||||
'nocache',
|
||||
function(params, content, data, repeat)
|
||||
{
|
||||
return content;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'block',
|
||||
'textformat',
|
||||
function(params, content, data, repeat)
|
||||
{
|
||||
if (!content) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var wrap = params.__get('wrap',80);
|
||||
var wrap_char = params.__get('wrap_char','\n');
|
||||
var wrap_cut = params.__get('wrap_cut',false);
|
||||
var indent_char = params.__get('indent_char',' ');
|
||||
var indent = params.__get('indent',0);
|
||||
var indentStr = (new Array(indent+1)).join(indent_char);
|
||||
var indent_first = params.__get('indent_first',0);
|
||||
var indentFirstStr = (new Array(indent_first+1)).join(indent_char);
|
||||
|
||||
var style = params.__get('style','');
|
||||
|
||||
if (style == 'email') {
|
||||
wrap = 72;
|
||||
}
|
||||
|
||||
var paragraphs = content.split(/[\r\n]{2}/);
|
||||
for (var i=0; i<paragraphs.length; ++i) {
|
||||
var p = paragraphs[i];
|
||||
if (!p) {
|
||||
continue;
|
||||
}
|
||||
p = p.replace(/^\s+|\s+$/,'').replace(/\s+/g,' ');
|
||||
if (indent_first> 0 ) {
|
||||
p = indentFirstStr + p;
|
||||
}
|
||||
p = modifiers.wordwrap(p, wrap-indent, wrap_char, wrap_cut);
|
||||
if (indent > 0) {
|
||||
p = p.replace(/^/mg, indentStr);
|
||||
}
|
||||
paragraphs[i] = p;
|
||||
}
|
||||
var s = paragraphs.join(wrap_char+wrap_char);
|
||||
if ('assign' in params)
|
||||
{
|
||||
assignVar(params.assign, s, data);
|
||||
return '';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
register modifiers
|
||||
*/
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'capitalize',
|
||||
function(s, upDigits, lcRest) {
|
||||
var re = new RegExp(upDigits ? '[^a-zA-Z_\u00E0-\u00FC]+' : '[^a-zA-Z0-9_\u00E0-\u00FC]');
|
||||
var found = null;
|
||||
var res = '';
|
||||
if (lcRest) {
|
||||
s = s.toLowerCase();
|
||||
}
|
||||
for (found=s.match(re); found; found=s.match(re))
|
||||
{
|
||||
var word = s.slice(0,found.index);
|
||||
if (word.match(/\d/))
|
||||
{
|
||||
res += word;
|
||||
}
|
||||
else
|
||||
{
|
||||
res += word.charAt(0).toUpperCase() + word.slice(1);
|
||||
}
|
||||
res += s.slice(found.index, found.index+found[0].length);
|
||||
s = s.slice(found.index+found[0].length);
|
||||
}
|
||||
if (s.match(/\d/))
|
||||
{
|
||||
return res + s;
|
||||
}
|
||||
return res + s.charAt(0).toUpperCase() + s.slice(1);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'cat',
|
||||
function(s, value)
|
||||
{
|
||||
value = value ? value : '';
|
||||
return s + value;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'count',
|
||||
function(v, recursive)
|
||||
{
|
||||
if (v === null || typeof v === 'undefined') {
|
||||
return 0;
|
||||
} else if (v.constructor !== Array && v.constructor !== Object) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
recursive = Boolean(recursive);
|
||||
var k, cnt = 0;
|
||||
for (k in v)
|
||||
{
|
||||
if (v.hasOwnProperty(k))
|
||||
{
|
||||
cnt++;
|
||||
if (recursive && v[k] && (v[k].constructor === Array || v[k].constructor === Object)) {
|
||||
cnt += modifiers.count(v[k], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'count_characters',
|
||||
function(s, includeWhitespaces)
|
||||
{
|
||||
return includeWhitespaces ? s.length : s.replace(/\s/g,'').length;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'count_paragraphs',
|
||||
function(s)
|
||||
{
|
||||
var found = s.match(/\n+/g);
|
||||
if (found)
|
||||
{
|
||||
return found.length+1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'count_sentences',
|
||||
function(s)
|
||||
{
|
||||
var found = s.match(/[^\s]\.(?!\w)/g);
|
||||
if (found)
|
||||
{
|
||||
return found.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'count_words',
|
||||
function(s)
|
||||
{
|
||||
var found = s.match(/\w+/g);
|
||||
if (found)
|
||||
{
|
||||
return found.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'date_format',
|
||||
function(s, fmt, defaultDate)
|
||||
{
|
||||
return jSmart.prototype.PHPJS('strftime','date_format').strftime(fmt?fmt:'%b %e, %Y', jSmart.prototype.makeTimeStamp(s?s:defaultDate));
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'defaultValue',
|
||||
function(s, value)
|
||||
{
|
||||
return (s && s!='null' && s!='undefined') ? s : (value ? value : '');
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'unescape',
|
||||
function(s, esc_type, char_set)
|
||||
{
|
||||
s = new String(s);
|
||||
esc_type = esc_type || 'html';
|
||||
char_set = char_set || 'UTF-8';
|
||||
|
||||
switch (esc_type)
|
||||
{
|
||||
case 'html':
|
||||
return s.replace(/</g, '<').replace(/>/g,'>').replace(/'/g,"'").replace(/"/g,'"');
|
||||
case 'entity':
|
||||
case 'htmlall':
|
||||
return jSmart.prototype.PHPJS('html_entity_decode','unescape').html_entity_decode(s, 0);
|
||||
case 'url':
|
||||
return jSmart.prototype.PHPJS('rawurldecode','unescape').rawurldecode(s);
|
||||
};
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'escape',
|
||||
function(s, esc_type, char_set, double_encode)
|
||||
{
|
||||
s = new String(s);
|
||||
esc_type = esc_type || 'html';
|
||||
char_set = char_set || 'UTF-8';
|
||||
double_encode = (typeof double_encode != 'undefined') ? Boolean(double_encode) : true;
|
||||
|
||||
switch (esc_type)
|
||||
{
|
||||
case 'html':
|
||||
if (double_encode) {
|
||||
s = s.replace(/&/g, '&');
|
||||
}
|
||||
return s.replace(/</g,'<').replace(/>/g,'>').replace(/'/g,''').replace(/"/g,'"');
|
||||
case 'htmlall':
|
||||
return jSmart.prototype.PHPJS('htmlentities','escape').htmlentities(s, 3, char_set);
|
||||
case 'url':
|
||||
return jSmart.prototype.PHPJS('rawurlencode','escape').rawurlencode(s);
|
||||
case 'urlpathinfo':
|
||||
return jSmart.prototype.PHPJS('rawurlencode','escape').rawurlencode(s).replace(/%2F/g, '/');
|
||||
case 'quotes':
|
||||
return s.replace(/(^|[^\\])'/g, "$1\\'");
|
||||
case 'hex':
|
||||
var res = '';
|
||||
for (var i=0; i<s.length; ++i)
|
||||
{
|
||||
res += '%' + jSmart.prototype.PHPJS('bin2hex','escape').bin2hex(s.substr(i,1));
|
||||
}
|
||||
return res;
|
||||
case 'hexentity':
|
||||
var res = '';
|
||||
for (var i=0; i<s.length; ++i) {
|
||||
res += '&#x' + jSmart.prototype.PHPJS('bin2hex','escape').bin2hex(s.substr(i,1)).toLowerCase() + ';';
|
||||
}
|
||||
return res;
|
||||
case 'decentity':
|
||||
var res = '';
|
||||
for (var i=0; i<s.length; ++i) {
|
||||
res += '&#' + jSmart.prototype.PHPJS('ord','escape').ord(s.substr(i,1)) + ';';
|
||||
}
|
||||
return res;
|
||||
case 'mail':
|
||||
return s.replace(/@/g,' [AT] ').replace(/[.]/g,' [DOT] ');
|
||||
case 'nonstd':
|
||||
var res = '';
|
||||
for (var i=0; i<s.length; ++i)
|
||||
{
|
||||
var _ord = jSmart.prototype.PHPJS('ord','escape').ord(s.substr(i,1));
|
||||
if (_ord >= 126) {
|
||||
res += '&#' + _ord + ';';
|
||||
} else {
|
||||
res += s.substr(i, 1);
|
||||
}
|
||||
|
||||
}
|
||||
return res;
|
||||
case 'javascript':
|
||||
return s.replace(/\\/g,'\\\\').replace(/'/g,"\\'").replace(/"/g,'\\"').replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/<\//g,'<\/');
|
||||
};
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'indent',
|
||||
function(s, repeat, indentWith)
|
||||
{
|
||||
repeat = repeat ? repeat : 4;
|
||||
indentWith = indentWith ? indentWith : ' ';
|
||||
|
||||
var indentStr = '';
|
||||
while (repeat--)
|
||||
{
|
||||
indentStr += indentWith;
|
||||
}
|
||||
|
||||
var tail = s.match(/\n+$/);
|
||||
return indentStr + s.replace(/\n+$/,'').replace(/\n/g,'\n'+indentStr) + (tail ? tail[0] : '');
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'lower',
|
||||
function(s)
|
||||
{
|
||||
return s.toLowerCase();
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'nl2br',
|
||||
function(s)
|
||||
{
|
||||
return s.replace(/\n/g,'<br />\n');
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
only modifiers (flags) 'i' and 'm' are supported
|
||||
backslashes should be escaped e.g. \\s
|
||||
*/
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'regex_replace',
|
||||
function(s, re, replaceWith)
|
||||
{
|
||||
var pattern = re.match(/^ *\/(.*)\/(.*) *$/);
|
||||
return (new String(s)).replace(new RegExp(pattern[1],'g'+(pattern.length>1?pattern[2]:'')), replaceWith);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'replace',
|
||||
function(s, search, replaceWith)
|
||||
{
|
||||
if (!search)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
s = new String(s);
|
||||
search = new String(search);
|
||||
replaceWith = new String(replaceWith);
|
||||
var res = '';
|
||||
var pos = -1;
|
||||
for (pos=s.indexOf(search); pos>=0; pos=s.indexOf(search))
|
||||
{
|
||||
res += s.slice(0,pos) + replaceWith;
|
||||
pos += search.length;
|
||||
s = s.slice(pos);
|
||||
}
|
||||
return res + s;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'spacify',
|
||||
function(s, space)
|
||||
{
|
||||
if (!space)
|
||||
{
|
||||
space = ' ';
|
||||
}
|
||||
return s.replace(/(\n|.)(?!$)/g,'$1'+space);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'noprint',
|
||||
function(s)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'string_format',
|
||||
function(s, fmt)
|
||||
{
|
||||
return jSmart.prototype.PHPJS('sprintf','string_format').sprintf(fmt,s);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'strip',
|
||||
function(s, replaceWith)
|
||||
{
|
||||
replaceWith = replaceWith ? replaceWith : ' ';
|
||||
return (new String(s)).replace(/[\s]+/g, replaceWith);
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'strip_tags',
|
||||
function(s, addSpace)
|
||||
{
|
||||
addSpace = (addSpace==null) ? true : addSpace;
|
||||
return (new String(s)).replace(/<[^>]*?>/g, addSpace ? ' ' : '');
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'truncate',
|
||||
function(s, length, etc, breakWords, middle)
|
||||
{
|
||||
length = length ? length : 80;
|
||||
etc = (etc!=null) ? etc : '...';
|
||||
|
||||
if (s.length <= length)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
length -= Math.min(length,etc.length);
|
||||
if (middle)
|
||||
{
|
||||
//one of floor()'s should be replaced with ceil() but it so in Smarty
|
||||
return s.slice(0,Math.floor(length/2)) + etc + s.slice(s.length-Math.floor(length/2));
|
||||
}
|
||||
|
||||
if (!breakWords)
|
||||
{
|
||||
s = s.slice(0,length+1).replace(/\s+?(\S+)?$/,'');
|
||||
}
|
||||
|
||||
return s.slice(0,length) + etc;
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'upper',
|
||||
function(s)
|
||||
{
|
||||
return s.toUpperCase();
|
||||
}
|
||||
);
|
||||
|
||||
jSmart.prototype.registerPlugin(
|
||||
'modifier',
|
||||
'wordwrap',
|
||||
function(s, width, wrapWith, breakWords)
|
||||
{
|
||||
width = width || 80;
|
||||
wrapWith = wrapWith || '\n';
|
||||
|
||||
var lines = s.split('\n');
|
||||
for (var i=0; i<lines.length; ++i)
|
||||
{
|
||||
var line = lines[i];
|
||||
var parts = ''
|
||||
while (line.length > width)
|
||||
{
|
||||
var pos = 0;
|
||||
var found = line.slice(pos).match(/\s+/);
|
||||
for (;found && (pos+found.index)<=width; found=line.slice(pos).match(/\s+/))
|
||||
{
|
||||
pos += found.index + found[0].length;
|
||||
}
|
||||
pos = pos || (breakWords ? width : (found ? found.index+found[0].length : line.length));
|
||||
parts += line.slice(0,pos).replace(/\s+$/,'');// + wrapWith;
|
||||
if (pos < line.length)
|
||||
{
|
||||
parts += wrapWith;
|
||||
}
|
||||
line = line.slice(pos);
|
||||
}
|
||||
lines[i] = parts + line;
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
String.prototype.fetch = function(data)
|
||||
{
|
||||
var tpl = new jSmart(this);
|
||||
return tpl.fetch(data);
|
||||
};
|
||||
|
||||
if (typeof module === "object" && module && typeof module.exports === "object") {
|
||||
module.exports = jSmart;
|
||||
} else {
|
||||
if (typeof global !== "undefined") {
|
||||
global.jSmart = jSmart;
|
||||
}
|
||||
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define("jSmart", [], function () { return jSmart; });
|
||||
}
|
||||
}
|
||||
})();
|
||||
10
frameworks/jsmart/jsmart.min.js
vendored
Normal file
10
frameworks/jsmart/jsmart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
62
js/theme.js
62
js/theme.js
|
|
@ -170,8 +170,6 @@ $(document).ready(function(){
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
//function commentOpenUI(obj, id) {
|
||||
// $(document).unbind( "click.commentOpen", handler );
|
||||
|
|
@ -451,4 +449,62 @@ function cmtBbOpen(id) {
|
|||
}
|
||||
function cmtBbClose(id) {
|
||||
$("#comment-edit-bb-" + id).hide();
|
||||
}
|
||||
}
|
||||
|
||||
function contact_filter(item) {
|
||||
// get the html content from the js template of the contact-wrapper
|
||||
contact_tpl = unescape($(".javascript-template[rel=contact-template]").html());
|
||||
|
||||
var variables = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
username: item.username,
|
||||
thumb: item.thumb,
|
||||
img_hover: item.img_hover,
|
||||
edit_hover: item.edit_hover,
|
||||
account_type: item.account_type,
|
||||
photo_menu: item.photo_menu,
|
||||
alt_text: item.alt_text,
|
||||
dir_icon: item.dir_icon,
|
||||
sparkle: item.sparkle,
|
||||
itemurl: item.itemurl,
|
||||
url: item.url,
|
||||
network: item.network,
|
||||
tags: item.tags,
|
||||
details: item.details,
|
||||
};
|
||||
|
||||
// open a new jSmart instance with the template
|
||||
var tpl = new jSmart (contact_tpl);
|
||||
|
||||
// replace the variable with the values
|
||||
var html = tpl.fetch(variables);
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function filter_replace(item) {
|
||||
|
||||
return item.name;
|
||||
}
|
||||
|
||||
(function( $ ) {
|
||||
$.fn.contact_filter = function(backend_url, typ, autosubmit, onselect) {
|
||||
if(typeof typ === 'undefined') typ = '';
|
||||
if(typeof autosubmit === 'undefined') autosubmit = false;
|
||||
|
||||
// Autocomplete contacts
|
||||
contacts = {
|
||||
match: /(^)([^\n]+)$/,
|
||||
index: 2,
|
||||
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
|
||||
replace: filter_replace,
|
||||
template: contact_filter,
|
||||
};
|
||||
|
||||
this.attr('autocomplete','off');
|
||||
var a = this.textcomplete([contacts], {className:'accontacts', zIndex:10000, appendTo: '#contact-list'});
|
||||
|
||||
a.on('textComplete:select', function(e, value, strategy) { $(".dropdown-menu.textcomplete-dropdown.media-list").show(); });
|
||||
};
|
||||
})( jQuery );
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ $("nav").bind('nav-update', function(e,data)
|
|||
<script src="<?=$frio?>/frameworks/justifiedGallery/jquery.justifiedGallery.min.js"></script>
|
||||
<script src="<?=$frio?>/frameworks/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js"></script>
|
||||
<script src="<?=$frio?>/frameworks/flexMenu/flexmenu.custom.js"></script>
|
||||
<script src="<?=$frio?>/frameworks/jsmart/jsmart.js"></script>
|
||||
<script src="<?=$frio?>/js/theme.js"></script>
|
||||
<script src="<?=$frio?>/js/acl.js"></script>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
|
||||
{{* use a smaller picture on very small displays (e.g. mobiles) *}}
|
||||
<div class="contact-photo-image-wrapper hidden-lg hidden-md">
|
||||
<div class="contact-photo-image-wrapper hidden-lg hidden-md hidden-sm">
|
||||
<img class="contact-photo-xs media-object" src="{{$contact.thumb}}" {{$contact.sparkle}} alt="{{$contact.name}}" />
|
||||
|
||||
{{* Overlay background on hover the avatar picture *}}
|
||||
|
|
@ -73,3 +73,83 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{{* the following part is a nearly a copy of the part above but it is modyfied for working with js.
|
||||
We use this part to filter the contacts with jquery.textcomplete *}}
|
||||
<div class="javascript-template" rel="contact-template" style="display: none">
|
||||
<div class="contact-wrapper media" id="contact-entry-wrapper-{$id}" >
|
||||
|
||||
{{* This is a wrapper for the contact picture and the dropdown menu with contact relating actions *}}
|
||||
<div class="contact-photo-wrapper dropdown pull-left" >
|
||||
<div class="contact-entry-photo mframe" id="contact-entry-photo-{$id}" >
|
||||
|
||||
<a class="dropdown-toggle" id="contact-photo-menu-{$id}" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" >
|
||||
<div class="contact-photo-image-wrapper hidden-xs">
|
||||
<img class="contact-photo media-object xl" src="{$thumb}" {11} alt="{$name}" />
|
||||
|
||||
{{* Overlay background on hover the avatar picture *}}
|
||||
<div class="contact-photo-overlay">
|
||||
<span class="contact-photo-overlay-content xl"><i class="fa fa-angle-down"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{* use a smaller picture on very small displays (e.g. mobiles) *}}
|
||||
<div class="contact-photo-image-wrapper hidden-lg hidden-md hidden-sm">
|
||||
<img class="contact-photo-xs media-object" src="{$thumb}" {11} alt="{$name}" />
|
||||
|
||||
{{* Overlay background on hover the avatar picture *}}
|
||||
<div class="contact-photo-overlay">
|
||||
<span class="contact-photo-overlay-content overlay-xs"><i class="fa fa-angle-down"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
{if $photo_menu}
|
||||
<ul class="contact-photo-menu menu-popup dropdown-menu " id="contact-photo-menu-{$id}" role="menu" aria-labelledby="contact-photo-menu-{$id}">
|
||||
{foreach $photo_menu as $c}
|
||||
{if $c.2}
|
||||
<li role="menuitem"><a target="redir" href="{$c.1}">{$c.0}</a></li>
|
||||
{elseif $c.3}
|
||||
<li role="menuitem"><a onclick="addToModal('{$c.1}')">{$c.0}</a></li>
|
||||
{else}
|
||||
<li role="menuitem"><a href="{$c.1}">{$c.0}</a></li>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</ul>
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="media-body"> {{* @todo There is a bug with this class - the browser freezes if the screensize is to small - but only fith textcomplete*}}
|
||||
{{* The contact description (e.g. Name, Network, kind of connection and so on *}}
|
||||
<div class="contact-entry-desc">
|
||||
<div class="contact-entry-name" id="contact-entry-name-{$id}" >
|
||||
<h4 class="media-heading">{$name}
|
||||
{if $account_type} <small class="contact-entry-details" id="contact-entry-accounttype-{$id}">({$account_type})</small>{/if}
|
||||
{if $account_type == 'Forum'}<i class="fa fa-comments-o" aria-hidden="true"></i>{/if}
|
||||
{{* @todo this needs some changing in core because $contact.account_type contains a translated string which may notbe the same in every language *}}
|
||||
</h4>
|
||||
</div>
|
||||
{if $alt_text}<div class="contact-entry-details" id="contact-entry-rel-{$id}" >{$alt_text}</div>{/if}
|
||||
{if $itemurl}<div class="contact-entry-details" id="contact-entry-url-{$id}" >{$itemurl}</div>{/if}
|
||||
{if $tags}<div class="contact-entry-details" id="contact-entry-tags-{$id}" >{$tags}</div>{/if}
|
||||
{if $details}<div class="contact-entry-details" id="contact-entry-details-{$id}" >{$details}</div>{/if}
|
||||
{if $network}<div class="contact-entry-details" id="contact-entry-network-{$id}" >{$network}</div>{/if}
|
||||
</div>
|
||||
|
||||
{{* The checkbox to perform batch actions to these contacts (for batch actions have a look at contacts-template.tpl) *}}
|
||||
{{* if !$no_contacts_checkbox *}}
|
||||
{{if $multiselect}}
|
||||
<div class="checkbox contact-entry-checkbox pull-right">
|
||||
<input id="checkbox-{$id}" type="checkbox" class="contact-select pull-right" name="contact_batch[]" value="{$id}">
|
||||
<label for="checkbox-{$id}"></label>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
23
templates/contacts-head.tpl
Normal file
23
templates/contacts-head.tpl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Add contact_filter autocompletion to the search field
|
||||
$("#contacts-search").contact_filter(baseurl + '/acl', 'r', true);
|
||||
|
||||
// Hide the viewcontact_wrapper if there is an input in the search field
|
||||
// We are doing this to let the the contact_filter replace the original
|
||||
// shown contacts
|
||||
$("#contacts-search").keyup(function(){
|
||||
var elText = $(this).val();
|
||||
if(elText.length !== 0) {
|
||||
$("#viewcontact_wrapper").hide();
|
||||
$("ul.textcomplete-dropdown").addClass("show media-list");
|
||||
} else {
|
||||
$("#viewcontact_wrapper").show();
|
||||
$("ul.textcomplete-dropdown").removeClass("show");
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -49,14 +49,15 @@
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clear">
|
||||
|
||||
{{* format each contact with the contact_template.tpl *}}
|
||||
<ul id="viewcontact_wrapper" class="viewcontact_wrapper media-list">
|
||||
{{foreach $contacts as $contact}}
|
||||
<li>{{include file="contact_template.tpl"}}</li>
|
||||
{{/foreach}}
|
||||
</ul>
|
||||
<div class="clear"></div>
|
||||
<div id="contact-list">
|
||||
{{* format each contact with the contact_template.tpl *}}
|
||||
<ul id="viewcontact_wrapper" class="viewcontact_wrapper media-list">
|
||||
{{foreach $contacts as $contact}}
|
||||
<li>{{include file="contact_template.tpl"}}</li>
|
||||
{{/foreach}}
|
||||
</ul>
|
||||
</div>
|
||||
<div id="contact-edit-end"></div>
|
||||
</form>
|
||||
|
||||
|
|
|
|||
63
theme.php
63
theme.php
|
|
@ -34,6 +34,7 @@ function frio_install() {
|
|||
register_hook('item_photo_menu', 'view/theme/frio/theme.php', 'frio_item_photo_menu');
|
||||
register_hook('contact_photo_menu', 'view/theme/frio/theme.php', 'frio_contact_photo_menu');
|
||||
register_hook('nav_info', 'view/theme/frio/theme.php', 'frio_remote_nav');
|
||||
register_hook('acl_lookup_end', 'view/theme/frio/theme.php', 'frio_acl_lookup');
|
||||
|
||||
logger("installed theme frio");
|
||||
}
|
||||
|
|
@ -41,7 +42,9 @@ function frio_install() {
|
|||
function frio_uninstall() {
|
||||
unregister_hook('prepare_body_final', 'view/theme/frio/theme.php', 'frio_item_photo_links');
|
||||
unregister_hook('item_photo_menu', 'view/theme/frio/theme.php', 'frio_item_photo_menu');
|
||||
unregister_hook('contact_photo_menu', 'view/theme/frio/theme.php', 'frio_contact_photo_menu');
|
||||
unregister_hook('nav_info', 'view/theme/frio/theme.php', 'frio_remote_nav');
|
||||
unregister_hook('acl_lookup_end', 'view/theme/frio/theme.php', 'frio_acl_lookup');
|
||||
|
||||
logger("uninstalled theme frio");
|
||||
}
|
||||
|
|
@ -244,3 +247,63 @@ function frio_remote_nav($a,&$nav) {
|
|||
$nav['sitename'] = $a->config['sitename'];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief: Search for contacts
|
||||
*
|
||||
* This function search for a users contacts. The code is copied from contact search
|
||||
* in /mod/contacts.php. With this function the contacts will permitted to acl_lookup()
|
||||
* and can grabbed as json. For this we use the type="r". This is usful to to let js
|
||||
* grab the contact data.
|
||||
* We use this to give the data to textcomplete and have a filter function at the
|
||||
* contact page.
|
||||
*
|
||||
* @param App $a The app data
|
||||
* @param array $results The array with the originals from acl_lookup()
|
||||
*/
|
||||
function frio_acl_lookup($a, &$results) {
|
||||
require_once("mod/contacts.php");
|
||||
|
||||
$nets = ((x($_GET,"nets")) ? notags(trim($_GET["nets"])) : "");
|
||||
|
||||
// we introduce a new search type, r should do the same query like it's
|
||||
// done in /mod/contacts for connections
|
||||
if($results["type"] == "r") {
|
||||
$searching = false;
|
||||
if($search) {
|
||||
$search_hdr = $search;
|
||||
$search_txt = dbesc(protect_sprintf(preg_quote($search)));
|
||||
$searching = true;
|
||||
}
|
||||
$sql_extra .= (($searching) ? " AND (`attag` LIKE '%%".dbesc($search_txt)."%%' OR `name` LIKE '%%".dbesc($search_txt)."%%' OR `nick` LIKE '%%".dbesc($search_txt)."%%') " : "");
|
||||
|
||||
if($nets)
|
||||
$sql_extra .= sprintf(" AND network = '%s' ", dbesc($nets));
|
||||
|
||||
$sql_extra2 = ((($sort_type > 0) && ($sort_type <= CONTACT_IS_FRIEND)) ? sprintf(" AND `rel` = %d ",intval($sort_type)) : '');
|
||||
|
||||
|
||||
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
|
||||
WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ",
|
||||
intval($_SESSION['uid']));
|
||||
if(count($r)) {
|
||||
$total = $r[0]["total"];
|
||||
}
|
||||
|
||||
$sql_extra3 = unavailable_networks();
|
||||
|
||||
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT 100 ",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
|
||||
$contacts = array();
|
||||
|
||||
if(count($r)) {
|
||||
foreach($r as $rr) {
|
||||
$contacts[] = _contact_detail_for_template($rr);
|
||||
}
|
||||
}
|
||||
|
||||
$results["items"] = $contacts;
|
||||
$results["tot"] = $total;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue