diff --git a/mod/hovercard.php b/mod/hovercard.php deleted file mode 100644 index d5951dbe0..000000000 --- a/mod/hovercard.php +++ /dev/null @@ -1,151 +0,0 @@ - - * License: GNU AFFERO GENERAL PUBLIC LICENSE (Version 3) - */ - -use Friendica\App; -use Friendica\Core\Config; -use Friendica\Core\Renderer; -use Friendica\Core\System; -use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\GContact; -use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Util\Strings; - -function hovercard_init(App $a) -{ - // Just for testing purposes - $_GET['mode'] = 'minimal'; -} - -function hovercard_content() -{ - $profileurl = $_REQUEST['profileurl'] ?? ''; - $datatype = ($_REQUEST['datatype'] ?? '') ?: 'json'; - - // Get out if the system doesn't have public access allowed - if (intval(Config::get('system', 'block_public'))) { - throw new \Friendica\Network\HTTPException\ForbiddenException(); - } - - // Return the raw content of the template. We use this to make templates usable for js functions. - // Look at hovercard.js (function getHoverCardTemplate()). - // This part should be moved in its own module. Maybe we could make more templates accessible. - // (We need to discuss possible security leaks before doing this) - if ($datatype == 'tpl') { - $templatecontent = get_template_content('hovercard.tpl'); - echo $templatecontent; - exit(); - } - - // If a contact is connected the url is internally changed to 'redir/CID'. We need the pure url to search for - // the contact. So we strip out the contact id from the internal url and look in the contact table for - // the real url (nurl) - if (strpos($profileurl, 'redir/') === 0) { - $cid = intval(substr($profileurl, 6)); - $remote_contact = DBA::selectFirst('contact', ['nurl'], ['id' => $cid]); - $profileurl = $remote_contact['nurl'] ?? ''; - } - - $contact = []; - // if it's the url containing https it should be converted to http - $nurl = Strings::normaliseLink(GContact::cleanContactUrl($profileurl)); - if (!$nurl) { - return; - } - - // Search for contact data - // Look if the local user has got the contact - if (local_user()) { - $contact = Contact::getDetailsByURL($nurl, local_user()); - } - - // If not then check the global user - if (!count($contact)) { - $contact = Contact::getDetailsByURL($nurl); - } - - // Feeds url could have been destroyed through "cleanContactUrl", so we now use the original url - if (!count($contact) && local_user()) { - $nurl = Strings::normaliseLink($profileurl); - $contact = Contact::getDetailsByURL($nurl, local_user()); - } - - if (!count($contact)) { - $nurl = Strings::normaliseLink($profileurl); - $contact = Contact::getDetailsByURL($nurl); - } - - if (!count($contact)) { - return; - } - - // Get the photo_menu - the menu if possible contact actions - if (local_user()) { - $actions = Contact::photoMenu($contact); - } else { - $actions = []; - } - - // Move the contact data to the profile array so we can deliver it to - $profile = [ - 'name' => $contact['name'], - 'nick' => $contact['nick'], - 'addr' => ($contact['addr'] ?? '') ?: $contact['url'], - 'thumb' => ProxyUtils::proxifyUrl($contact['thumb'], false, ProxyUtils::SIZE_THUMB), - 'url' => Contact::magicLink($contact['url']), - 'nurl' => $contact['nurl'], // We additionally store the nurl as identifier - 'location' => $contact['location'], - 'gender' => $contact['gender'], - 'about' => $contact['about'], - 'network_link' => Strings::formatNetworkName($contact['network'], $contact['url']), - 'tags' => $contact['keywords'], - 'bd' => $contact['birthday'] <= DBA::NULL_DATE ? '' : $contact['birthday'], - 'account_type' => Contact::getAccountType($contact), - 'actions' => $actions, - ]; - if ($datatype == 'html') { - $tpl = Renderer::getMarkupTemplate('hovercard.tpl'); - $o = Renderer::replaceMacros($tpl, [ - '$profile' => $profile, - ]); - - return $o; - } else { - System::jsonExit($profile); - } -} - -/** - * @brief Get the raw content of a template file - * - * @param string $template The name of the template - * @param string $root Directory of the template - * - * @return string|bool Output the raw content if existent, otherwise false - * @throws Exception - */ -function get_template_content($template, $root = '') -{ - // We load the whole template system to get the filename. - // Maybe we can do it a little bit smarter if I get time. - $templateEngine = Renderer::getTemplateEngine(); - $template = $templateEngine->getTemplateFile($template, $root); - - $filename = $template->filename; - - // Get the content of the template file - if (file_exists($filename)) { - $content = file_get_contents($filename); - - return $content; - } - - return false; -} diff --git a/src/Model/Contact.php b/src/Model/Contact.php index a57c7b96e..2742e49df 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -983,41 +983,43 @@ class Contact extends BaseObject $ssl_url = str_replace('http://', 'https://', $url); + $nurl = Strings::normaliseLink($url); + // Fetch contact data from the contact table for the given user $s = DBA::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `nurl` = ? AND `uid` = ?", Strings::normaliseLink($url), $uid); + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`, `rel`, `pending` + FROM `contact` WHERE `nurl` = ? AND `uid` = ?", $nurl, $uid); $r = DBA::toArray($s); // Fetch contact data from the contact table for the given user, checking with the alias if (!DBA::isResult($r)) { $s = DBA::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", Strings::normaliseLink($url), $url, $ssl_url, $uid); + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`, `rel`, `pending` + FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", $nurl, $url, $ssl_url, $uid); $r = DBA::toArray($s); } // Fetch the data from the contact table with "uid=0" (which is filled automatically) if (!DBA::isResult($r)) { $s = DBA::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `nurl` = ? AND `uid` = 0", Strings::normaliseLink($url)); + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`, `rel`, `pending` + FROM `contact` WHERE `nurl` = ? AND `uid` = 0", $nurl); $r = DBA::toArray($s); } // Fetch the data from the contact table with "uid=0" (which is filled automatically) - checked with the alias if (!DBA::isResult($r)) { $s = DBA::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", Strings::normaliseLink($url), $url, $ssl_url); + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`, `rel`, `pending` + FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", $nurl, $url, $ssl_url); $r = DBA::toArray($s); } // Fetch the data from the gcontact table if (!DBA::isResult($r)) { $s = DBA::p("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, 0 AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` - FROM `gcontact` WHERE `nurl` = ?", Strings::normaliseLink($url)); + `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, 0 AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self`, 2 AS `rel`, 0 AS `pending` + FROM `gcontact` WHERE `nurl` = ?", $nurl); $r = DBA::toArray($s); } @@ -1121,7 +1123,7 @@ class Contact extends BaseObject // Fetch contact data from the contact table for the given user $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`, `rel`, `pending` FROM `contact` WHERE `addr` = '%s' AND `uid` = %d AND NOT `deleted`", DBA::escape($addr), intval($uid) @@ -1129,7 +1131,7 @@ class Contact extends BaseObject // Fetch the data from the contact table with "uid=0" (which is filled automatically) if (!DBA::isResult($r)) { $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`, `rel`, `pending` FROM `contact` WHERE `addr` = '%s' AND `uid` = 0 AND NOT `deleted`", DBA::escape($addr) ); @@ -1138,7 +1140,7 @@ class Contact extends BaseObject // Fetch the data from the gcontact table if (!DBA::isResult($r)) { $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` + `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self`, 2 AS `rel`, 0 AS `pending` FROM `gcontact` WHERE `addr` = '%s'", DBA::escape($addr) ); @@ -1225,28 +1227,40 @@ class Contact extends BaseObject $contact_drop_link = System::baseUrl() . '/contact/' . $contact['id'] . '/drop?confirm=1'; } + $follow_link = ''; + $unfollow_link = ''; + if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { + if ($contact['uid'] && in_array($contact['rel'], [self::SHARING, self::FRIEND])) { + $unfollow_link = 'unfollow?url=' . urlencode($contact['url']); + } elseif(!$contact['pending']) { + $follow_link = 'follow?url=' . urlencode($contact['url']); + } + } + /** * Menu array: * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ] */ if (empty($contact['uid'])) { - $connlnk = 'follow/?url=' . $contact['url']; $menu = [ - 'profile' => [L10n::t('View Profile'), $profile_link, true], - 'network' => [L10n::t('Network Posts'), $posts_link, false], - 'edit' => [L10n::t('View Contact'), $contact_url, false], - 'follow' => [L10n::t('Connect/Follow'), $connlnk, true], + 'profile' => [L10n::t('View Profile') , $profile_link , true], + 'network' => [L10n::t('Network Posts') , $posts_link , false], + 'edit' => [L10n::t('View Contact') , $contact_url , false], + 'follow' => [L10n::t('Connect/Follow'), $follow_link , true], + 'unfollow'=> [L10n::t('UnFollow') , $unfollow_link, true], ]; } else { $menu = [ - 'status' => [L10n::t('View Status'), $status_link, true], - 'profile' => [L10n::t('View Profile'), $profile_link, true], - 'photos' => [L10n::t('View Photos'), $photos_link, true], - 'network' => [L10n::t('Network Posts'), $posts_link, false], - 'edit' => [L10n::t('View Contact'), $contact_url, false], - 'drop' => [L10n::t('Drop Contact'), $contact_drop_link, false], - 'pm' => [L10n::t('Send PM'), $pm_url, false], - 'poke' => [L10n::t('Poke'), $poke_link, false], + 'status' => [L10n::t('View Status') , $status_link , true], + 'profile' => [L10n::t('View Profile') , $profile_link , true], + 'photos' => [L10n::t('View Photos') , $photos_link , true], + 'network' => [L10n::t('Network Posts') , $posts_link , false], + 'edit' => [L10n::t('View Contact') , $contact_url , false], + 'drop' => [L10n::t('Drop Contact') , $contact_drop_link, false], + 'pm' => [L10n::t('Send PM') , $pm_url , false], + 'poke' => [L10n::t('Poke') , $poke_link , false], + 'follow' => [L10n::t('Connect/Follow'), $follow_link , true], + 'unfollow'=> [L10n::t('UnFollow') , $unfollow_link , true], ]; if (!empty($contact['pending'])) { diff --git a/src/Module/Contact/Hovercard.php b/src/Module/Contact/Hovercard.php new file mode 100644 index 000000000..20290e0ac --- /dev/null +++ b/src/Module/Contact/Hovercard.php @@ -0,0 +1,104 @@ + $cid]); + $contact_url = $remote_contact['nurl'] ?? ''; + } + + $contact = []; + + // if it's the url containing https it should be converted to http + $contact_nurl = Strings::normaliseLink(GContact::cleanContactUrl($contact_url)); + if (!$contact_nurl) { + throw new HTTPException\BadRequestException(); + } + + // Search for contact data + // Look if the local user has got the contact + if (Session::isAuthenticated()) { + $contact = Contact::getDetailsByURL($contact_nurl, local_user()); + } + + // If not then check the global user + if (!count($contact)) { + $contact = Contact::getDetailsByURL($contact_nurl); + } + + // Feeds url could have been destroyed through "cleanContactUrl", so we now use the original url + if (!count($contact) && Session::isAuthenticated()) { + $contact_nurl = Strings::normaliseLink($contact_url); + $contact = Contact::getDetailsByURL($contact_nurl, local_user()); + } + + if (!count($contact)) { + $contact_nurl = Strings::normaliseLink($contact_url); + $contact = Contact::getDetailsByURL($contact_nurl); + } + + if (!count($contact)) { + throw new HTTPException\NotFoundException(); + } + + // Get the photo_menu - the menu if possible contact actions + if (Session::isAuthenticated()) { + $actions = Contact::photoMenu($contact); + } else { + $actions = []; + } + + // Move the contact data to the profile array so we can deliver it to + $tpl = Renderer::getMarkupTemplate('hovercard.tpl'); + $o = Renderer::replaceMacros($tpl, [ + '$profile' => [ + 'name' => $contact['name'], + 'nick' => $contact['nick'], + 'addr' => $contact['addr'] ?: $contact['url'], + 'thumb' => Proxy::proxifyUrl($contact['thumb'], false, Proxy::SIZE_THUMB), + 'url' => Contact::magicLink($contact['url']), + 'nurl' => $contact['nurl'], + 'location' => $contact['location'], + 'gender' => $contact['gender'], + 'about' => $contact['about'], + 'network_link' => Strings::formatNetworkName($contact['network'], $contact['url']), + 'tags' => $contact['keywords'], + 'bd' => $contact['birthday'] <= DBA::NULL_DATE ? '' : $contact['birthday'], + 'account_type' => Contact::getAccountType($contact), + 'actions' => $actions, + ], + ]); + + echo $o; + exit(); + } +} diff --git a/static/routes.config.php b/static/routes.config.php index ee0669118..1f2fe0ad1 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -74,23 +74,25 @@ return [ '/compose[/{type}]' => [Module\Item\Compose::class, [R::GET, R::POST]], '/contact' => [ - '[/]' => [Module\Contact::class, [R::GET]], - '/{id:\d+}[/]' => [Module\Contact::class, [R::GET, R::POST]], - '/{id:\d+}/archive' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/block' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/conversations' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/drop' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/ignore' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/posts' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/update' => [Module\Contact::class, [R::GET]], - '/{id:\d+}/updateprofile' => [Module\Contact::class, [R::GET]], - '/archived' => [Module\Contact::class, [R::GET]], - '/batch' => [Module\Contact::class, [R::GET, R::POST]], - '/pending' => [Module\Contact::class, [R::GET]], - '/blocked' => [Module\Contact::class, [R::GET]], - '/hidden' => [Module\Contact::class, [R::GET]], - '/ignored' => [Module\Contact::class, [R::GET]], + '[/]' => [Module\Contact::class, [R::GET]], + '/{id:\d+}[/]' => [Module\Contact::class, [R::GET, R::POST]], + '/{id:\d+}/archive' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/block' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/conversations' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/drop' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/ignore' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/posts' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/update' => [Module\Contact::class, [R::GET]], + '/{id:\d+}/updateprofile' => [Module\Contact::class, [R::GET]], + '/archived' => [Module\Contact::class, [R::GET]], + '/batch' => [Module\Contact::class, [R::GET, R::POST]], + '/pending' => [Module\Contact::class, [R::GET]], + '/blocked' => [Module\Contact::class, [R::GET]], + '/hidden' => [Module\Contact::class, [R::GET]], + '/ignored' => [Module\Contact::class, [R::GET]], + '/hovercard' => [Module\Contact\Hovercard::class, [R::GET]], ], + '/credits' => [Module\Credits::class, [R::GET]], '/delegation'=> [Module\Delegation::class, [R::GET, R::POST]], '/dirfind' => [Module\Search\Directory::class, [R::GET]], diff --git a/view/templates/hovercard.tpl b/view/templates/hovercard.tpl index 017e096af..4f41c204e 100644 --- a/view/templates/hovercard.tpl +++ b/view/templates/hovercard.tpl @@ -28,6 +28,7 @@ {{if $profile.actions.network}}{{/if}} {{if $profile.actions.edit}}{{/if}} {{if $profile.actions.follow}}{{/if}} + {{if $profile.actions.unfollow}}{{/if}} diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index f1c78abc7..b0458d513 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1800,6 +1800,28 @@ aside .panel-body { font-size: 14px; } +/* Contact avatar click card */ +.userinfo.click-card { + position: relative; +} + +.userinfo.click-card > *:hover:after { + content: '⌄'; + color: #bebebe; + font-size: 1em; + font-weight: bold; + background-color: #ffffff; + text-align: center; + line-height: 40%; + position: absolute; + top: 0; + left: 0; + width: 33%; + height: 33%; + opacity: .8; + border-radius: 0 0 40% 0; +} + /* The lock symbol popup */ #panel { position: absolute; diff --git a/view/theme/frio/frameworks/jsmart/jsmart.custom.js b/view/theme/frio/frameworks/jsmart/jsmart.custom.js deleted file mode 100644 index 7a611a20e..000000000 --- a/view/theme/frio/frameworks/jsmart/jsmart.custom.js +++ /dev/null @@ -1,3456 +0,0 @@ -/*! - * jSmart Javascript template engine - * https://github.com/umakantp/jsmart - * - * Copyright 2011-2015, Max Miroshnikov - * Umakant Patil - * 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= 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': 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=0 && i=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\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 (typeof a == 'undefined') - { - a = []; - } - if (typeof a != '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; i0; --i) - { - i -= bundleOp(i-1, tree, precedence); - } - } - else - { - for (i=0; i= 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') + ''; - for (var nm in v) - { - if (v.hasOwnProperty(nm)) - { - s += indent + ' ' + nm + ' : ' + jSmart.prototype.print_r(v[nm],indent+' ') + ''; - } - } - 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 += '' + nm + '' + jSmart.prototype.print_r(data[nm],'') + ''; - } - dbgWnd.document.write(" \ - \ - \ - jSmart Debug Console \ - \ - \ - \ - jSmart Debug Console \ - assigned template variables \ - " + sVars + " \ - \ - \ - "); - 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 ? '' : '') : ''); - - s += '' + output[useName?p:i++]; - s += (labels ? '' : ''); - 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 = ''; - return href ? ''+s+'' : 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 = '' + output[useName ? p : i++] + ''; - res.push(s); - } - } - var name = params.__get('name',false); - return (name ? ('\n' + res.join('\n') + '\n') : 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 += '\n'; - var i=0; - for (i=0; i' + months[i] + '\n'; - } - s += '\n' - - s += '\n'; - for (i=0; i<31; ++i) - { - s += '' + i + '\n'; - } - s += '\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\n'; - for (var col=0; col' + (idx < loop.length ? loop[idx] : trailpad) + '\n'; - } - s += '\n'; - } - - var sHead = ''; - if (colNames.length) - { - sHead = '\n'; - for (var i=0; i' + colNames[hdir=='right'?i:colNames.length-1-i] + ''; - } - sHead += '\n'; - } - - return '' + (caption?'\n'+caption+'':'') + sHead + '\n\n' + s + '\n\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 = '' + text + ''; - - if (encode == 'javascript') - { - s = "document.write('" + s + "');"; - var sEncoded = ''; - for (var i=0; ieval(unescape(\'' + sEncoded + "'))"; - } - else if (encode == 'javascript_charcode') - { - var codes = []; - for (var i=0; i\n\n\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' + tEncoded + ''; - } - 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 ''; - } - - content = new String(content); - - 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 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) { - if (typeof s != 'string') { - return s; - } - 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 new String(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) - { - s = new String(s); - return includeWhitespaces ? s.length : s.replace(/\s/g,'').length; - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'count_paragraphs', - function(s) - { - var found = (new String(s)).match(/\n+/g); - if (found) - { - return found.length+1; - } - return 1; - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'count_sentences', - function(s) - { - if (typeof s == 'string') - { - var found = s.match(/[^\s]\.(?!\w)/g); - if (found) - { - return found.length; - } - } - return 0; - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'count_words', - function(s) - { - if (typeof s == 'string') - { - 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, 1); - 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,'"'); - 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= 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) - { - s = new String(s); - 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 new String(s).toLowerCase(); - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'nl2br', - function(s) - { - return new String(s).replace(/\n/g,'\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 (new String(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) - { - s = new String(s); - 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 (new String(s)).toUpperCase(); - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'wordwrap', - function(s, width, wrapWith, breakWords) - { - width = width || 80; - wrapWith = wrapWith || '\n'; - - var lines = (new String(s)).split('\n'); - for (var i=0; i 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; }); - } - } -})(); diff --git a/view/theme/frio/frameworks/jsmart/jsmart.js b/view/theme/frio/frameworks/jsmart/jsmart.js deleted file mode 100644 index 758e92824..000000000 --- a/view/theme/frio/frameworks/jsmart/jsmart.js +++ /dev/null @@ -1,3456 +0,0 @@ -/*! - * jSmart Javascript template engine - * https://github.com/umakantp/jsmart - * - * Copyright 2011-2015, Max Miroshnikov - * Umakant Patil - * 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= 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': 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=0 && i=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\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 (typeof a == 'undefined') - { - a = []; - } - if (typeof a != '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; i0; --i) - { - i -= bundleOp(i-1, tree, precedence); - } - } - else - { - for (i=0; i= 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') + ''; - for (var nm in v) - { - if (v.hasOwnProperty(nm)) - { - s += indent + ' ' + nm + ' : ' + jSmart.prototype.print_r(v[nm],indent+' ') + ''; - } - } - 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 += '' + nm + '' + jSmart.prototype.print_r(data[nm],'') + ''; - } - dbgWnd.document.write(" \ - \ - \ - jSmart Debug Console \ - \ - \ - \ - jSmart Debug Console \ - assigned template variables \ - " + sVars + " \ - \ - \ - "); - 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 ? '' : '') : ''); - - s += '' + output[useName?p:i++]; - s += (labels ? '' : ''); - 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 = ''; - return href ? ''+s+'' : 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 = '' + output[useName ? p : i++] + ''; - res.push(s); - } - } - var name = params.__get('name',false); - return (name ? ('\n' + res.join('\n') + '\n') : 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 += '\n'; - var i=0; - for (i=0; i' + months[i] + '\n'; - } - s += '\n' - - s += '\n'; - for (i=0; i<31; ++i) - { - s += '' + i + '\n'; - } - s += '\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\n'; - for (var col=0; col' + (idx < loop.length ? loop[idx] : trailpad) + '\n'; - } - s += '\n'; - } - - var sHead = ''; - if (colNames.length) - { - sHead = '\n'; - for (var i=0; i' + colNames[hdir=='right'?i:colNames.length-1-i] + ''; - } - sHead += '\n'; - } - - return '' + (caption?'\n'+caption+'':'') + sHead + '\n\n' + s + '\n\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 = '' + text + ''; - - if (encode == 'javascript') - { - s = "document.write('" + s + "');"; - var sEncoded = ''; - for (var i=0; ieval(unescape(\'' + sEncoded + "'))"; - } - else if (encode == 'javascript_charcode') - { - var codes = []; - for (var i=0; i\n\n\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' + tEncoded + ''; - } - 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 ''; - } - - content = new String(content); - - 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 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) { - if (typeof s != 'string') { - return s; - } - 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 new String(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) - { - s = new String(s); - return includeWhitespaces ? s.length : s.replace(/\s/g,'').length; - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'count_paragraphs', - function(s) - { - var found = (new String(s)).match(/\n+/g); - if (found) - { - return found.length+1; - } - return 1; - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'count_sentences', - function(s) - { - if (typeof s == 'string') - { - var found = s.match(/[^\s]\.(?!\w)/g); - if (found) - { - return found.length; - } - } - return 0; - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'count_words', - function(s) - { - if (typeof s == 'string') - { - 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, 1); - 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,'"'); - 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= 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) - { - s = new String(s); - 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 new String(s).toLowerCase(); - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'nl2br', - function(s) - { - return new String(s).replace(/\n/g,'\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 (new String(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) - { - s = new String(s); - 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 (new String(s)).toUpperCase(); - } - ); - - jSmart.prototype.registerPlugin( - 'modifier', - 'wordwrap', - function(s, width, wrapWith, breakWords) - { - width = width || 80; - wrapWith = wrapWith || '\n'; - - var lines = (new String(s)).split('\n'); - for (var i=0; i 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; }); - } - } -})(); diff --git a/view/theme/frio/frameworks/jsmart/jsmart.min.js b/view/theme/frio/frameworks/jsmart/jsmart.min.js deleted file mode 100644 index 51764df6e..000000000 --- a/view/theme/frio/frameworks/jsmart/jsmart.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! - * jSmart Javascript template engine (v2.15.0) - * https://github.com/umakantp/jsmart - * http://opensource.org/licenses/LGPL-3.0 - * - * Copyright 2011-2015, Max Miroshnikov - * Umakant Patil - */ -!function(){function obMerge(a){for(var b=1;b=0&&b.substr(j-1,1).match(/\s/))continue;if(!--c){var k=b.slice(e.length,j).replace(/[\r\n]/g," "),l=k.match(i);if(l)return l.index=d,l[0]=b.slice(0,j+f.length),l}0>c&&(c=0)}return null}function findCloseTag(a,b,c){var d="",e=null,f=null,g=0;do{if(e&&(g+=e[0].length),e=findTag(a,c),!e)throw new Error("Unclosed {"+b+"}");d+=c.slice(0,e.index),g+=e.index,c=c.slice(e.index+e[0].length),f=findTag(b,d),f&&(d=d.slice(f.index+f[0].length))}while(f);return e.index=g,e}function findElseTag(a,b,c,d){for(var e=0,f=findTag(c,d);f;f=findTag(c,d)){var g=findTag(a,d);if(!g||g.index>f.index)return f.index+=e,f;d=d.slice(g.index+g[0].length),e+=g.index+g[0].length;var h=findCloseTag(b,a,d);d=d.slice(h.index+h[0].length),e+=h.index+h[0].length}return null}function execute(code,data){if("string"==typeof code)with({__code:code})with(modifiers)with(data)try{return eval(__code)}catch(e){throw new Error(e.message+" in \n"+code)}return code}function executeByFuncObject(a,b){try{return a.apply(this,b)}catch(c){throw new Error(c.message)}}function assignVar(a,b,c){a.match(/\[\]$/)?c[a.replace(/\[\]$/,"")].push(b):c[a]=b}function parse(a,b){for(var c=findTag("",a);c;c=findTag("",a)){c.index&&parseText(a.slice(0,c.index),b),a=a.slice(c.index+c[0].length);var d=c[1].match(/^\s*(\w+)(.*)$/);if(d){var e=d[1],f=d.length>2?d[2].replace(/^\s+|\s+$/g,""):"";if(e in buildInFunctions){var g=buildInFunctions[e],h=("parseParams"in g?g.parseParams:parseParams)(f);if("block"==g.type){a=a.replace(/^\n/,"");var i=findCloseTag("/"+e,e+" +[^}]*",a);g.parse(h,b,a.slice(0,i.index)),a=a.slice(i.index+i[0].length)}else g.parse(h,b),"extends"==e&&(b=[]);a=a.replace(/^\n/,"")}else if(e in plugins){var j=plugins[e];if("block"==j.type){var i=findCloseTag("/"+e,e+" +[^}]*",a);parsePluginBlock(e,parseParams(f),b,a.slice(0,i.index)),a=a.slice(i.index+i[0].length)}else"function"==j.type&&parsePluginFunc(e,parseParams(f),b);("append"==e||"assign"==e||"capture"==e||"eval"==e||"include"==e)&&(a=a.replace(/^\n/,""))}else buildInFunctions.expression.parse(c[1],b)}else{var k=buildInFunctions.expression.parse(c[1],b);"build-in"==k.type&&"operator"==k.name&&"="==k.op&&(a=a.replace(/^\n/,""))}}return a&&parseText(a,b),b}function parseText(a,b){if(parseText.parseEmbeddedVars)for(var c=/([$][\w@]+)|`([^`]*)`/,d=c.exec(a);d;d=c.exec(a))b.push({type:"text",data:a.slice(0,d.index)}),b.push(parseExpression(d[1]?d[1]:d[2]).tree),a=a.slice(d.index+d[0].length);return b.push({type:"text",data:a}),b}function parseFunc(a,b,c){return b.__parsed.name=parseText(a,[])[0],c.push({type:"plugin",name:"__func",params:b}),c}function parseOperator(a,b,c,d){d.push({type:"build-in",name:"operator",op:a,optype:b,precedence:c,params:{}})}function parseVar(a,b,c){for(var d=b.token,e=[{type:"text",data:c.replace(/^(\w+)@(key|index|iteration|first|last|show|total)/gi,"$1__$2")}],f=/^(?:\.|\s*->\s*|\[\s*)/,g=a.match(f);g;g=a.match(f)){b.token+=g[0],a=a.slice(g[0].length);var h={value:"",tree:[]};if(g[0].match(/\[/)){h=parseExpression(a),h&&(b.token+=h.value,e.push(h.tree),a=a.slice(h.value.length));var i=a.match(/\s*\]/);i&&(b.token+=i[0],a=a.slice(i[0].length))}else{var j=parseModifiers.stop;if(parseModifiers.stop=!0,lookUp(a,h)){b.token+=h.value;var k=h.tree[0];"plugin"==k.type&&"__func"==k.name&&(k.hasOwner=!0),e.push(k),a=a.slice(h.value.length)}else h=!1;parseModifiers.stop=j}h||e.push({type:"text",data:""})}return b.tree.push({type:"var",parts:e}),b.value+=b.token.substr(d.length),onParseVar(b.token),a}function onParseVar(){}function parseModifiers(a,b){if(!parseModifiers.stop){var c=a.match(/^\|(\w+)/);if(c){b.value+=c[0];var d="default"==c[1]?"defaultValue":c[1];a=a.slice(c[0].length).replace(/^\s+/,""),parseModifiers.stop=!0;for(var e=[],f=a.match(/^\s*:\s*/);f;f=a.match(/^\s*:\s*/)){b.value+=a.slice(0,f[0].length),a=a.slice(f[0].length);var g={value:"",tree:[]};lookUp(a,g)?(b.value+=g.value,e.push(g.tree[0]),a=a.slice(g.value.length)):parseText("",e)}parseModifiers.stop=!1,e.unshift(b.tree.pop()),b.tree.push(parseFunc(d,{__parsed:e},[])[0]),parseModifiers(a,b)}}}function lookUp(a,b){if(!a)return!1;if(a.substr(0,jSmart.prototype.left_delimiter.length)==jSmart.prototype.left_delimiter){var c=findTag("",a);if(c)return b.token=c[0],b.value+=c[0],parse(c[0],b.tree),parseModifiers(a.slice(b.value.length),b),!0}for(var d=0;dc;++c)if(2==c||10==c)for(b=a.length;b>0;--b)b-=bundleOp(b-1,a,c);else for(b=0;bd;case"<=":return g>=d;case">":return d>g;case">=":return d>=g;case"===":return d===g;case"!==":return d!==g}}},section:{type:"block",parse:function(a,b,c){var d=[],e=[];b.push({type:"build-in",name:"section",params:a,subTree:d,subTreeElse:e});var f=findElseTag("section [^}]+","/section","sectionelse",c);f?(parse(c.slice(0,f.index),d),parse(c.slice(f.index+f[0].length).replace(/^[\r\n]/,""),e)):parse(c,d)},process:function(a,b){var c=getActualParamValues(a.params,b),d={};b.smarty.section[c.__get("name",null,0)]=d;var e=c.__get("show",!0);if(d.show=e,!e)return process(a.subTreeElse,b);var f=parseInt(c.__get("start",0)),g=c.loop instanceof Object?countProperties(c.loop):isNaN(c.loop)?0:parseInt(c.loop),h=parseInt(c.__get("step",1)),i=parseInt(c.__get("max"));isNaN(i)&&(i=Number.MAX_VALUE),0>f?(f+=g,0>f&&(f=0)):f>=g&&(f=g?g-1:0);for(var j=0,k=0,l=f;l>=0&&g>l&&i>j;l+=h,++j)k=l;d.total=j,d.loop=j,j=0;var m="";for(l=f;l>=0&&g>l&&i>j&&!b.smarty["break"];l+=h,++j)d.first=l==f,d.last=0>l+h||l+h>=g,d.index=l,d.index_prev=l-h,d.index_next=l+h,d.iteration=d.rownum=j+1,m+=process(a.subTree,b),b.smarty["continue"]=!1;return b.smarty["break"]=!1,j?m:process(a.subTreeElse,b)}},setfilter:{type:"block",parseParams:function(a){return[parseExpression("__t()|"+a).tree]},parse:function(a,b,c){b.push({type:"build-in",name:"setfilter",params:a,subTree:parse(c,[])})},process:function(a,b){tpl_modifiers=a.params;var c=process(a.subTree,b);return tpl_modifiers=[],c}},"for":{type:"block",parseParams:function(a){var b=a.match(/^\s*\$(\w+)\s*=\s*([^\s]+)\s*to\s*([^\s]+)\s*(?:step\s*([^\s]+))?\s*(.*)$/);if(!b)throw new Error("Invalid {for} parameters: "+a);return parseParams("varName='"+b[1]+"' from="+b[2]+" to="+b[3]+" step="+(b[4]?b[4]:"1")+" "+b[5])},parse:function(a,b,c){var d=[],e=[];b.push({type:"build-in",name:"for",params:a,subTree:d,subTreeElse:e});var f=findElseTag("for\\s[^}]+","/for","forelse",c);f?(parse(c.slice(0,f.index),d),parse(c.slice(f.index+f[0].length),e)):parse(c,d)},process:function(a,b){var c=getActualParamValues(a.params,b),d=parseInt(c.__get("from")),e=parseInt(c.__get("to")),f=parseInt(c.__get("step"));isNaN(f)&&(f=1);var g=parseInt(c.__get("max"));isNaN(g)&&(g=Number.MAX_VALUE);for(var h=0,i="",j=Math.min(Math.ceil(((f>0?e-d:d-e)+1)/Math.abs(f)),g),k=parseInt(c.from);j>h&&!b.smarty["break"];k+=f,++h)b[c.varName]=k,i+=process(a.subTree,b),b.smarty["continue"]=!1;return b.smarty["break"]=!1,h||(i=process(a.subTreeElse,b)),i}},"if":{type:"block",parse:function(a,b,c){var d=[],e=[];b.push({type:"build-in",name:"if",params:a,subTreeIf:d,subTreeElse:e});var f=findElseTag("if\\s+[^}]+","/if","else[^}]*",c);if(f){parse(c.slice(0,f.index),d),c=c.slice(f.index+f[0].length);var g=f[1].match(/^else\s*if(.*)/);g?buildInFunctions["if"].parse(parseParams(g[1]),e,c.replace(/^\n/,"")):parse(c.replace(/^\n/,""),e)}else parse(c,d)},process:function(a,b){var c=getActualParamValues(a.params,b)[0];return c&&!(c instanceof Array&&0==c.length||"object"==typeof c&&isEmptyObject(c))?process(a.subTreeIf,b):process(a.subTreeElse,b)}},foreach:{type:"block",parseParams:function(a){var b=a.match(/^\s*([$].+)\s*as\s*[$](\w+)\s*(=>\s*[$](\w+))?\s*$/i);return b&&(a="from="+b[1]+" item="+(b[4]||b[2]),b[4]&&(a+=" key="+b[2])),parseParams(a)},parse:function(a,b,c){var d=[],e=[];b.push({type:"build-in",name:"foreach",params:a,subTree:d,subTreeElse:e});var f=findElseTag("foreach\\s[^}]+","/foreach","foreachelse",c);f?(parse(c.slice(0,f.index),d),parse(c.slice(f.index+f[0].length).replace(/^[\r\n]/,""),e)):parse(c,d)},process:function(a,b){var c=getActualParamValues(a.params,b),d=c.from;d instanceof Object||(d=[d]);var e=countProperties(d);b[c.item+"__total"]=e,"name"in c&&(b.smarty.foreach[c.name]={},b.smarty.foreach[c.name].total=e);var f="",g=0;for(var h in d)if(d.hasOwnProperty(h)){if(b.smarty["break"])break;b[c.item+"__key"]=isNaN(h)?h:parseInt(h),"key"in c&&(b[c.key]=b[c.item+"__key"]),b[c.item]=d[h],b[c.item+"__index"]=parseInt(g),b[c.item+"__iteration"]=parseInt(g+1),b[c.item+"__first"]=0===g,b[c.item+"__last"]=g==e-1,"name"in c&&(b.smarty.foreach[c.name].index=parseInt(g),b.smarty.foreach[c.name].iteration=parseInt(g+1),b.smarty.foreach[c.name].first=0===g?1:"",b.smarty.foreach[c.name].last=g==e-1?1:""),++g,f+=process(a.subTree,b),b.smarty["continue"]=!1}return b.smarty["break"]=!1,b[c.item+"__show"]=g>0,c.name&&(b.smarty.foreach[c.name].show=g>0?1:""),g>0?f:process(a.subTreeElse,b)}},"function":{type:"block",parse:function(a,b,c){var d=[];plugins[trimQuotes(a.name?a.name:a[0])]={type:"function",subTree:d,defautParams:a,process:function(a,b){var c=getActualParamValues(this.defautParams,b);return delete c.name,process(this.subTree,obMerge({},b,c,a))}},parse(c,d)}},php:{type:"block",parse:function(){}},"extends":{type:"function",parse:function(a,b){b.splice(0,b.length),getTemplate(trimQuotes(a.file?a.file:a[0]),b)}},block:{type:"block",parse:function(a,b,c){b.push({type:"build-in",name:"block",params:a}),a.append=findInArray(a,"append")>=0,a.prepend=findInArray(a,"prepend")>=0,a.hide=findInArray(a,"hide")>=0,a.hasChild=a.hasParent=!1,onParseVar=function(b){b.match(/^\s*[$]smarty.block.child\s*$/)&&(a.hasChild=!0),b.match(/^\s*[$]smarty.block.parent\s*$/)&&(a.hasParent=!0)};var b=parse(c,[]);onParseVar=function(){};var d=trimQuotes(a.name?a.name:a[0]);d in blocks||(blocks[d]=[]),blocks[d].push({tree:b,params:a})},process:function(a,b){b.smarty.block.parent=b.smarty.block.child="";var c=trimQuotes(a.params.name?a.params.name:a.params[0]);return this.processBlocks(blocks[c],blocks[c].length-1,b),b.smarty.block.child},processBlocks:function(a,b,c){if(!b&&a[b].params.hide)return void(c.smarty.block.child="");for(var d=!0,e=!1;b>=0;--b){if(a[b].params.hasParent){var f=c.smarty.block.child;c.smarty.block.child="",this.processBlocks(a,b-1,c),c.smarty.block.parent=c.smarty.block.child,c.smarty.block.child=f}var f=c.smarty.block.child,g=process(a[b].tree,c);c.smarty.block.child=f,a[b].params.hasChild?c.smarty.block.child=g:d?c.smarty.block.child=g+c.smarty.block.child:e&&(c.smarty.block.child+=g),d=a[b].params.append,e=a[b].params.prepend}}},strip:{type:"block",parse:function(a,b,c){parse(c.replace(/[ \t]*[\r\n]+[ \t]*/g,""),b)}},literal:{type:"block",parse:function(a,b,c){parseText(c,b)}},ldelim:{type:"function",parse:function(a,b){parseText(jSmart.prototype.left_delimiter,b)}},rdelim:{type:"function",parse:function(a,b){parseText(jSmart.prototype.right_delimiter,b)}},"while":{type:"block",parse:function(a,b,c){b.push({type:"build-in",name:"while",params:a,subTree:parse(c,[])})},process:function(a,b){for(var c="";getActualParamValues(a.params,b)[0]&&!b.smarty["break"];)c+=process(a.subTree,b),b.smarty["continue"]=!1;return b.smarty["break"]=!1,c}}},plugins={},modifiers={},files={},blocks=null,scripts=null,tpl_modifiers=[],tokens=[{re:/^\$([\w@]+)/,parse:function(a,b){parseModifiers(parseVar(b,a,RegExp.$1),a)}},{re:/^(true|false)/i,parse:function(a){parseText(a.token.match(/true/i)?"1":"",a.tree)}},{re:/^'([^'\\]*(?:\\.[^'\\]*)*)'/,parse:function(a,b){parseText(evalString(RegExp.$1),a.tree),parseModifiers(b,a)}},{re:/^"([^"\\]*(?:\\.[^"\\]*)*)"/,parse:function(a,b){var c=evalString(RegExp.$1),d=c.match(tokens[0].re);if(d){var e={token:d[0],tree:[]};if(parseVar(c,e,d[1]),e.token.length==c.length)return void a.tree.push(e.tree[0])}parseText.parseEmbeddedVars=!0,a.tree.push({type:"plugin",name:"__quoted",params:{__parsed:parse(c,[])}}),parseText.parseEmbeddedVars=!1,parseModifiers(b,a)}},{re:/^(\w+)\s*[(]([)]?)/,parse:function(a,b){var c=RegExp.$1,d=RegExp.$2,e=parseParams(d?"":b,/^\s*,\s*/);parseFunc(c,e,a.tree),a.value+=e.toString(),parseModifiers(b.slice(e.toString().length),a)}},{re:/^\s*\(\s*/,parse:function(a){var b=[];a.tree.push(b),b.parent=a.tree,a.tree=b}},{re:/^\s*\)\s*/,parse:function(a){a.tree.parent&&(a.tree=a.tree.parent)}},{re:/^\s*(\+\+|--)\s*/,parse:function(a){a.tree.length&&"var"==a.tree[a.tree.length-1].type?parseOperator(RegExp.$1,"post-unary",1,a.tree):parseOperator(RegExp.$1,"pre-unary",1,a.tree)}},{re:/^\s*(===|!==|==|!=)\s*/,parse:function(a){parseOperator(RegExp.$1,"binary",6,a.tree)}},{re:/^\s+(eq|ne|neq)\s+/i,parse:function(a){var b=RegExp.$1.replace(/ne(q)?/,"!=").replace(/eq/,"==");parseOperator(b,"binary",6,a.tree)}},{re:/^\s*!\s*/,parse:function(a){parseOperator("!","pre-unary",2,a.tree)}},{re:/^\s+not\s+/i,parse:function(a){parseOperator("!","pre-unary",2,a.tree)}},{re:/^\s*(=|\+=|-=|\*=|\/=|%=)\s*/,parse:function(a){parseOperator(RegExp.$1,"binary",10,a.tree)}},{re:/^\s*(\*|\/|%)\s*/,parse:function(a){parseOperator(RegExp.$1,"binary",3,a.tree)}},{re:/^\s+mod\s+/i,parse:function(a){parseOperator("%","binary",3,a.tree)}},{re:/^\s*(\+|-)\s*/,parse:function(a){a.tree.length&&"operator"!=a.tree[a.tree.length-1].name?parseOperator(RegExp.$1,"binary",4,a.tree):parseOperator(RegExp.$1,"pre-unary",4,a.tree)}},{re:/^\s*(<=|>=|<>|<|>)\s*/,parse:function(a){parseOperator(RegExp.$1.replace(/<>/,"!="),"binary",5,a.tree)}},{re:/^\s+(lt|lte|le|gt|gte|ge)\s+/i,parse:function(a){var b=RegExp.$1.replace(/lt/,"<").replace(/l(t)?e/,"<=").replace(/gt/,">").replace(/g(t)?e/,">=");parseOperator(b,"binary",5,a.tree)}},{re:/^\s+(is\s+(not\s+)?div\s+by)\s+/i,parse:function(a){parseOperator(RegExp.$2?"div_not":"div","binary",7,a.tree)}},{re:/^\s+is\s+(not\s+)?(even|odd)(\s+by\s+)?\s*/i,parse:function(a){var b=RegExp.$1?"odd"==RegExp.$2?"even":"even_not":"odd"==RegExp.$2?"even_not":"even";parseOperator(b,"binary",7,a.tree),RegExp.$3||parseText("1",a.tree)}},{re:/^\s*(&&)\s*/,parse:function(a){parseOperator(RegExp.$1,"binary",8,a.tree)}},{re:/^\s*(\|\|)\s*/,parse:function(a){parseOperator(RegExp.$1,"binary",9,a.tree)}},{re:/^\s+and\s+/i,parse:function(a){parseOperator("&&","binary",11,a.tree)}},{re:/^\s+xor\s+/i,parse:function(a){parseOperator("xor","binary",12,a.tree)}},{re:/^\s+or\s+/i,parse:function(a){parseOperator("||","binary",13,a.tree)}},{re:/^#(\w+)#/,parse:function(a,b){var c={token:"$smarty",tree:[]};parseVar(".config."+RegExp.$1,c,"smarty"),a.tree.push(c.tree[0]),parseModifiers(b,a)}},{re:/^\s*\[\s*/,parse:function(a,b){var c=parseParams(b,/^\s*,\s*/,/^('[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"|\w+)\s*=>\s*/);parsePluginFunc("__array",c,a.tree),a.value+=c.toString();var d=b.slice(c.toString().length).match(/\s*\]/);d&&(a.value+=d[0])}},{re:/^[\d.]+/,parse:function(a,b){a.token=a.token.indexOf(".")>-1?parseFloat(a.token):parseInt(a.token,10),parseText(a.token,a.tree),parseModifiers(b,a)}},{re:/^\w+/,parse:function(a,b){parseText(a.token,a.tree),parseModifiers(b,a)}}];jSmart=function(a){this.tree=[],this.tree.blocks={},this.scripts={},this.default_modifiers=[],this.filters={variable:[],post:[]},this.smarty={smarty:{block:{},"break":!1,capture:{},"continue":!1,counter:{},cycle:{},foreach:{},section:{},now:Math.floor((new Date).getTime()/1e3),"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(a?a:"").replace(/\r\n/g,"\n"))),this.tree)},jSmart.prototype.fetch=function(a){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("object"==typeof a?a:{},this.smarty),varFilters=jSmart.prototype.filters_global.variable.concat(this.filters.variable);var b=process(this.tree,this.data);return jSmart.prototype.debugging&&plugins.debug.process([],this.data),applyFilters(jSmart.prototype.filters_global.post.concat(this.filters.post),b)},jSmart.prototype.escape_html=!1,jSmart.prototype.registerPlugin=function(a,b,c){"modifier"==a?modifiers[b]=c:plugins[b]={type:a,process:c}},jSmart.prototype.registerFilter=function(a,b){(this.tree?this.filters:jSmart.prototype.filters_global)["output"==a?"post":a].push(b)},jSmart.prototype.filters_global={pre:[],variable:[],post:[]},jSmart.prototype.configLoad=function(a,b,c){c=c?c:this.data;for(var d=a.replace(/\r\n/g,"\n").replace(/^\s+|\s+$/g,""),e=/^\s*(?:\[([^\]]+)\]|(?:(\w+)[ \t]*=[ \t]*("""|'[^'\\\n]*(?:\\.[^'\\\n]*)*'|"[^"\\\n]*(?:\\.[^"\\\n]*)*"|[^\n]*)))/m,f="",g=d.match(e);g;g=d.match(e)){if(d=d.slice(g.index+g[0].length),g[1])f=g[1];else if((!f||f==b)&&"."!=f.substr(0,1))if('"""'==g[3]){var h=d.match(/"""/);h&&(c.smarty.config[g[2]]=d.slice(0,h.index),d=d.slice(h.index+h[0].length))}else c.smarty.config[g[2]]=trimQuotes(g[3]);var i=d.match(/\n+/);if(!i)break;d=d.slice(i.index+i[0].length)}},jSmart.prototype.clearConfig=function(a){a?delete this.data.smarty.config[a]:this.data.smarty.config={}},jSmart.prototype.addDefaultModifier=function(a){a instanceof Array||(a=[a]);for(var b=0;b=b.smarty.cycle[c].arr.length||d)&&(b.smarty.cycle[c].index=0),a.__get("assign",!1)?(assignVar(a.assign,b.smarty.cycle[c].arr[b.smarty.cycle[c].index],b),""):a.__get("print",!0)?b.smarty.cycle[c].arr[b.smarty.cycle[c].index]:""}),jSmart.prototype.print_r=function(a,b){if(a instanceof Object){var c=(a instanceof Array?"Array["+a.length+"]":"Object")+"";for(var d in a)a.hasOwnProperty(d)&&(c+=b+" "+d+" : "+jSmart.prototype.print_r(a[d],b+" ")+"");return c}return a},jSmart.prototype.registerPlugin("function","debug",function(a,b){"undefined"!=typeof dbgWnd&&dbgWnd.close(),dbgWnd=window.open("","","width=680,height=600,resizable,scrollbars=yes");var c="",d=0;for(var e in b)c+=""+e+""+jSmart.prototype.print_r(b[e],"")+"";return dbgWnd.document.write(" jSmart Debug Console jSmart Debug Console assigned template variables "+c+" "),""}),jSmart.prototype.registerPlugin("function","eval",function(a,b){var c=[];parse(a.__get("var","",0),c);var d=process(c,b);return"assign"in a?(assignVar(a.assign,d,b),""):d}),jSmart.prototype.registerPlugin("function","fetch",function(a,b){var c=jSmart.prototype.getFile(a.__get("file",null,0));return"assign"in a?(assignVar(a.assign,c,b),""):c}),jSmart.prototype.registerPlugin("function","html_checkboxes",function(a,b){var c,d,e,f=a.__get("type","checkbox"),g=a.__get("name",f),h=a.__get("name",f),i=a.__get("values",a.options),j=a.__get("options",[]),k="options"in a,l=a.__get("selected",!1),m=a.__get("separator",""),n=Boolean(a.__get("labels",!0)),o=Boolean(a.__get("label_ids",!1)),p=[],q=0,r="";if("checkbox"==f&&(g+="[]"),!k)for(c in a.output)j.push(a.output[c]);for(c in i)i.hasOwnProperty(c)&&(d=k?c:i[c],e=h+"_"+d,r=n?o?'':"":"",r+='"+j[k?c:q++],r+=n?"":"",r+=m,p.push(r));return"assign"in a?(assignVar(a.assign,p,b),""):p.join("\n")}),jSmart.prototype.registerPlugin("function","html_image",function(a){var b,c=a.__get("file",null),d=a.__get("width",!1),e=a.__get("height",!1),f=a.__get("alt",""),g=a.__get("href",a.__get("link",!1)),h=a.__get("path_prefix",""),i={file:1,width:1,height:1,alt:1,href:1,basedir:1,path_prefix:1,link:1},j='",g?''+j+"":j}),jSmart.prototype.registerPlugin("function","html_options",function(a){var b,c=a.__get("values",a.options),d=a.__get("options",[]),e="options"in a;if(!e)for(b in a.output)d.push(a.output[b]);var f=a.__get("selected",!1),g=[],h="",i=0;for(b in c)c.hasOwnProperty(b)&&(h='"+d[e?b:i++]+"",g.push(h));var j=a.__get("name",!1);return(j?'\n'+g.join("\n")+"\n":g.join("\n"))+"\n"}),jSmart.prototype.registerPlugin("function","html_radios",function(a,b){return a.type="radio",plugins.html_checkboxes.process(a,b)}),jSmart.prototype.registerPlugin("function","html_select_date",function(a){var b=a.__get("prefix","Date_"),c=["January","February","March","April","May","June","July","August","September","October","November","December"],d="";d+='\n'; -var e=0;for(e=0;e'+c[e]+"\n";for(d+="\n",d+='\n',e=0;31>e;++e)d+=''+e+"\n";return d+="\n"}),jSmart.prototype.registerPlugin("function","html_table",function(a){var b,c=[];if(a.loop instanceof Array)c=a.loop;else for(b in a.loop)a.loop.hasOwnProperty(b)&&c.push(a.loop[b]);var d=a.__get("rows",!1),e=a.__get("cols",!1);e||(e=d?Math.ceil(c.length/d):3);var f=[];if(isNaN(e)){if("object"==typeof e)for(b in e)e.hasOwnProperty(b)&&f.push(e[b]);else f=e.split(/\s*,\s*/);e=f.length}d=d?d:Math.ceil(c.length/e);var g=a.__get("inner","cols"),h=a.__get("caption",""),i=a.__get("table_attr",'border="1"'),j=a.__get("th_attr",!1);j&&"object"!=typeof j&&(j=[j]);var k=a.__get("tr_attr",!1);k&&"object"!=typeof k&&(k=[k]);var l=a.__get("td_attr",!1);l&&"object"!=typeof l&&(l=[l]);for(var m=a.__get("trailpad"," "),n=a.__get("hdir","right"),o=a.__get("vdir","down"),p="",q=0;d>q;++q){p+="\n";for(var r=0;e>r;++r){var s="cols"==g?("down"==o?q:d-1-q)*e+("right"==n?r:e-1-r):("right"==n?r:e-1-r)*d+("down"==o?q:d-1-q);p+=""+(s\n"}p+="\n"}var t="";if(f.length){t="\n";for(var u=0;u"+f["right"==n?u:f.length-1-u]+"";t+="\n"}return""+(h?"\n"+h+"":"")+t+"\n\n"+p+"\n\n"}),jSmart.prototype.registerPlugin("function","include",function(a,b){var c=a.__get("file",null,0),d=obMerge({},b,a);d.smarty.template=c;var e=process(getTemplate(c,[],findInArray(a,"nocache")>=0),d);return"assign"in a?(assignVar(a.assign,e,b),""):e}),jSmart.prototype.registerPlugin("function","include_javascript",function(a,b){var c=a.__get("file",null,0);if(a.__get("once",!0)&&c in scripts)return"";scripts[c]=!0;var d=execute(jSmart.prototype.getJavascript(c),{$this:b});return"assign"in a?(assignVar(a.assign,d,b),""):d}),jSmart.prototype.registerPlugin("function","include_php",function(a,b){return plugins.include_javascript.process(a,b)}),jSmart.prototype.registerPlugin("function","insert",function(params,data){var fparams={};for(var nm in params)params.hasOwnProperty(nm)&&isNaN(nm)&¶ms[nm]&&"string"==typeof params[nm]&&"name"!=nm&&"assign"!=nm&&"script"!=nm&&(fparams[nm]=params[nm]);var prefix="insert_";"script"in params&&(eval(jSmart.prototype.getJavascript(params.script)),prefix="smarty_insert_");var func=eval(prefix+params.__get("name",null,0)),s=func(fparams,data);return"assign"in params?(assignVar(params.assign,s,data),""):s}),jSmart.prototype.registerPlugin("block","javascript",function(a,b,c){return c.$this=c,execute(b,c),delete c.$this,""}),jSmart.prototype.registerPlugin("function","config_load",function(a,b){return jSmart.prototype.configLoad(jSmart.prototype.getConfig(a.__get("file",null,0)),a.__get("section","",1),b),""}),jSmart.prototype.registerPlugin("function","mailto",function(a){var b=a.__get("address",null),c=a.__get("encode","none"),d=a.__get("text",b),e=jSmart.prototype.PHPJS("rawurlencode","mailto").rawurlencode(a.__get("cc","")).replace("%40","@"),f=jSmart.prototype.PHPJS("rawurlencode","mailto").rawurlencode(a.__get("bcc","")).replace("%40","@"),g=jSmart.prototype.PHPJS("rawurlencode","mailto").rawurlencode(a.__get("followupto","")).replace("%40","@"),h=jSmart.prototype.PHPJS("rawurlencode","mailto").rawurlencode(a.__get("subject","")),i=jSmart.prototype.PHPJS("rawurlencode","mailto").rawurlencode(a.__get("newsgroups","")),j=a.__get("extra","");if(b+=e?"?cc="+e:"",b+=f?(e?"&":"?")+"bcc="+f:"",b+=h?(e||f?"&":"?")+"subject="+h:"",b+=i?(e||f||h?"&":"?")+"newsgroups="+i:"",b+=g?(e||f||h||i?"&":"?")+"followupto="+g:"",s='"+d+"","javascript"==c){s="document.write('"+s+"');";for(var k="",l=0;leval(unescape(\''+k+"'))"}if("javascript_charcode"==c){for(var m=[],l=0;l\n\n\n"}if("hex"==c){if(b.match(/^.+\?.+$/))throw new Error("mailto: hex encoding does not work with extra attributes. Try javascript.");for(var n="",l=0;l"+o+""}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"));return"format"in params&&(res=jSmart.prototype.PHPJS("sprintf","math").sprintf(params.format,res)),"assign"in params?(assignVar(params.assign,res,data),""):res}),jSmart.prototype.registerPlugin("block","nocache",function(a,b){return b}),jSmart.prototype.registerPlugin("block","textformat",function(a,b,c){if(!b)return"";var d=a.__get("wrap",80),e=a.__get("wrap_char","\n"),f=a.__get("wrap_cut",!1),g=a.__get("indent_char"," "),h=a.__get("indent",0),i=new Array(h+1).join(g),j=a.__get("indent_first",0),k=new Array(j+1).join(g),l=a.__get("style","");"email"==l&&(d=72);for(var m=b.split(/[\r\n]{2}/),n=0;n0&&(o=k+o),o=modifiers.wordwrap(o,d-h,e,f),h>0&&(o=o.replace(/^/gm,i)),m[n]=o)}var p=m.join(e+e);return"assign"in a?(assignVar(a.assign,p,c),""):p}),jSmart.prototype.registerPlugin("modifier","capitalize",function(a,b,c){var d=new RegExp(b?"[^a-zA-Z_à-ü]+":"[^a-zA-Z0-9_à-ü]"),e=null,f="";for(c&&(a=a.toLowerCase()),e=a.match(d);e;e=a.match(d)){var g=a.slice(0,e.index);f+=g.match(/\d/)?g:g.charAt(0).toUpperCase()+g.slice(1),f+=a.slice(e.index,e.index+e[0].length),a=a.slice(e.index+e[0].length)}return a.match(/\d/)?f+a:f+a.charAt(0).toUpperCase()+a.slice(1)}),jSmart.prototype.registerPlugin("modifier","cat",function(a,b){return b=b?b:"",a+b}),jSmart.prototype.registerPlugin("modifier","count",function(a,b){if(null===a||"undefined"==typeof a)return 0;if(a.constructor!==Array&&a.constructor!==Object)return 1;b=Boolean(b);var c,d=0;for(c in a)a.hasOwnProperty(c)&&(d++,b&&a[c]&&(a[c].constructor===Array||a[c].constructor===Object)&&(d+=modifiers.count(a[c],!0)));return d}),jSmart.prototype.registerPlugin("modifier","count_characters",function(a,b){return b?a.length:a.replace(/\s/g,"").length}),jSmart.prototype.registerPlugin("modifier","count_paragraphs",function(a){var b=a.match(/\n+/g);return b?b.length+1:1}),jSmart.prototype.registerPlugin("modifier","count_sentences",function(a){var b=a.match(/[^\s]\.(?!\w)/g);return b?b.length:0}),jSmart.prototype.registerPlugin("modifier","count_words",function(a){var b=a.match(/\w+/g);return b?b.length:0}),jSmart.prototype.registerPlugin("modifier","date_format",function(a,b,c){return jSmart.prototype.PHPJS("strftime","date_format").strftime(b?b:"%b %e, %Y",jSmart.prototype.makeTimeStamp(a?a:c))}),jSmart.prototype.registerPlugin("modifier","defaultValue",function(a,b){return a&&"null"!=a&&"undefined"!=a?a:b?b:""}),jSmart.prototype.registerPlugin("modifier","unescape",function(a,b,c){switch(a=new String(a),b=b||"html",c=c||"UTF-8",b){case"html":return a.replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,'"');case"entity":case"htmlall":return jSmart.prototype.PHPJS("html_entity_decode","unescape").html_entity_decode(a,0);case"url":return jSmart.prototype.PHPJS("rawurldecode","unescape").rawurldecode(a)}return a}),jSmart.prototype.registerPlugin("modifier","escape",function(a,b,c,d){switch(a=new String(a),b=b||"html",c=c||"UTF-8",d="undefined"!=typeof d?Boolean(d):!0,b){case"html":return d&&(a=a.replace(/&/g,"&")),a.replace(//g,">").replace(/'/g,"'").replace(/"/g,""");case"htmlall":return jSmart.prototype.PHPJS("htmlentities","escape").htmlentities(a,3,c);case"url":return jSmart.prototype.PHPJS("rawurlencode","escape").rawurlencode(a);case"urlpathinfo":return jSmart.prototype.PHPJS("rawurlencode","escape").rawurlencode(a).replace(/%2F/g,"/");case"quotes":return a.replace(/(^|[^\\])'/g,"$1\\'");case"hex":for(var e="",f=0;f=126?""+g+";":a.substr(f,1)}return e;case"javascript":return a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/"/g,'\\"').replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/<\//g,"")}return a}),jSmart.prototype.registerPlugin("modifier","indent",function(a,b,c){b=b?b:4,c=c?c:" ";for(var d="";b--;)d+=c;var e=a.match(/\n+$/);return d+a.replace(/\n+$/,"").replace(/\n/g,"\n"+d)+(e?e[0]:"")}),jSmart.prototype.registerPlugin("modifier","lower",function(a){return a.toLowerCase()}),jSmart.prototype.registerPlugin("modifier","nl2br",function(a){return a.replace(/\n/g,"\n")}),jSmart.prototype.registerPlugin("modifier","regex_replace",function(a,b,c){var d=b.match(/^ *\/(.*)\/(.*) *$/);return new String(a).replace(new RegExp(d[1],"g"+(d.length>1?d[2]:"")),c)}),jSmart.prototype.registerPlugin("modifier","replace",function(a,b,c){if(!b)return a;a=new String(a),b=new String(b),c=new String(c);var d="",e=-1;for(e=a.indexOf(b);e>=0;e=a.indexOf(b))d+=a.slice(0,e)+c,e+=b.length,a=a.slice(e);return d+a}),jSmart.prototype.registerPlugin("modifier","spacify",function(a,b){return b||(b=" "),a.replace(/(\n|.)(?!$)/g,"$1"+b)}),jSmart.prototype.registerPlugin("modifier","noprint",function(){return""}),jSmart.prototype.registerPlugin("modifier","string_format",function(a,b){return jSmart.prototype.PHPJS("sprintf","string_format").sprintf(b,a)}),jSmart.prototype.registerPlugin("modifier","strip",function(a,b){return b=b?b:" ",new String(a).replace(/[\s]+/g,b)}),jSmart.prototype.registerPlugin("modifier","strip_tags",function(a,b){return b=null==b?!0:b,new String(a).replace(/<[^>]*?>/g,b?" ":"")}),jSmart.prototype.registerPlugin("modifier","truncate",function(a,b,c,d,e){return b=b?b:80,c=null!=c?c:"...",a.length<=b?a:(b-=Math.min(b,c.length),e?a.slice(0,Math.floor(b/2))+c+a.slice(a.length-Math.floor(b/2)):(d||(a=a.slice(0,b+1).replace(/\s+?(\S+)?$/,"")),a.slice(0,b)+c))}),jSmart.prototype.registerPlugin("modifier","upper",function(a){return a.toUpperCase()}),jSmart.prototype.registerPlugin("modifier","wordwrap",function(a,b,c,d){b=b||80,c=c||"\n";for(var e=a.split("\n"),f=0;fb;){for(var i=0,j=g.slice(i).match(/\s+/);j&&i+j.index<=b;j=g.slice(i).match(/\s+/))i+=j.index+j[0].length;i=i||(d?b:j?j.index+j[0].length:g.length),h+=g.slice(0,i).replace(/\s+$/,""),i * */ -$(document).ready(function(){ - // Elements with the class "userinfo" will get a hover-card. - // Note that this elements does need a href attribute which links to - // a valid profile url - $("body").on("mouseover", ".userinfo, .wall-item-responses a, .wall-item-bottom .mention a", function(e) { - var timeNow = new Date().getTime(); - removeAllhoverCards(e,timeNow); - var hoverCardData = false; - var hrefAttr = false; - var targetElement = $(this); +$(document).ready(function () { + let $body = $('body'); + // Prevents normal click action on click hovercard elements + $body.on('click', '.userinfo.click-card', function (e) { + e.preventDefault(); + }); + // This event listener needs to be declared before the one that removes + // all cards so that we can stop the immediate propagation of the event + // Since the manual popover appears instantly and the hovercard removal is + // on a 100ms delay, leaving event propagation immediately hides any click hovercard + $body.on('mousedown', '.userinfo.click-card', function (e) { + e.stopImmediatePropagation(); + let timeNow = new Date().getTime(); - // get href-attribute - if(targetElement.is('[href]')) { - hrefAttr = targetElement.attr('href'); - } else { - return true; - } + let contactUrl = false; + let targetElement = $(this); - // no hover card if the element has the no-hover-card class - if(targetElement.hasClass('no-hover-card')) { - return true; - } + // get href-attribute + if (targetElement.is('[href]')) { + contactUrl = targetElement.attr('href'); + } else { + return true; + } - // no hovercard for anchor links - if(hrefAttr.substring(0,1) == '#') { - return true; - } + // no hovercard for anchor links + if (contactUrl.substring(0, 1) === '#') { + return true; + } - targetElement.attr('data-awaiting-hover-card',timeNow); - - // Take link href attribute as link to the profile - var profileurl = hrefAttr; - // the url to get the contact and template data - var url = baseurl + "/hovercard"; - - // store the title in an other data attribute beause bootstrap - // popover destroys the title.attribute. We can restore it later - var title = targetElement.attr("title"); - targetElement.attr({"data-orig-title": title, title: ""}); - - // if the device is a mobile open the hover card by click and not by hover - if(typeof is_mobile != "undefined") { - targetElement[0].removeAttribute("href"); - var hctrigger = 'click'; - } else { - var hctrigger = 'manual'; - }; - - // Timeout until the hover-card does appear - setTimeout(function(){ - if(targetElement.is(":hover") && parseInt(targetElement.attr('data-awaiting-hover-card'),10) == timeNow) { - if($('.hovercard').length == 0) { // no card if there already is one open - // get an additional data atribute if the card is active - targetElement.attr('data-hover-card-active',timeNow); - // get the whole html content of the hover card and - // push it to the bootstrap popover - getHoverCardContent(profileurl, url, function(data){ - if(data) { - targetElement.popover({ - html: true, - placement: function () { - // Calculate the placement of the the hovercard (if top or bottom) - // The placement depence on the distance between window top and the element - // which triggers the hover-card - var get_position = $(targetElement).offset().top - $(window).scrollTop(); - if (get_position < 270 ){ - return "bottom"; - } - return "top"; - }, - trigger: hctrigger, - template: '', - content: data, - container: "body", - sanitizeFn: function (content) { - return DOMPurify.sanitize(content) - }, - }).popover('show'); - } - }); - } - } - }, 500); - }).on("mouseleave", ".userinfo, .wall-item-responses a, .wall-item-bottom .mention a", function(e) { // action when mouse leaves the hover-card - var timeNow = new Date().getTime(); - // copy the original title to the title atribute - var title = $(this).attr("data-orig-title"); - $(this).attr({"data-orig-title": "", title: title}); - removeAllhoverCards(e,timeNow); + openHovercard(targetElement, contactUrl, timeNow); }); - - - // hover cards should be removed very easily, e.g. when any of these events happen - $('body').on("mouseleave touchstart scroll click dblclick mousedown mouseup submit keydown keypress keyup", function(e){ - // remove hover card only for desktiop user, since on mobile we openen the hovercards + // hover cards should be removed very easily, e.g. when any of these events happens + $body.on('mouseleave touchstart scroll mousedown submit keydown', function (e) { + // remove hover card only for desktiop user, since on mobile we open the hovercards // by click event insteadof hover - if(typeof is_mobile == "undefined") { - var timeNow = new Date().getTime(); - removeAllhoverCards(e,timeNow); - }; + removeAllHovercards(e, new Date().getTime()); + }); + + $body.on('mouseover', '.userinfo.hover-card, .wall-item-responses a, .wall-item-bottom .mention a', function (e) { + let timeNow = new Date().getTime(); + removeAllHovercards(e, timeNow); + let contactUrl = false; + let targetElement = $(this); + + // get href-attribute + if (targetElement.is('[href]')) { + contactUrl = targetElement.attr('href'); + } else { + return true; + } + + // no hover card if the element has the no-hover-card class + if (targetElement.hasClass('no-hover-card')) { + return true; + } + + // no hovercard for anchor links + if (contactUrl.substring(0, 1) === '#') { + return true; + } + + targetElement.attr('data-awaiting-hover-card', timeNow); + + // Delay until the hover-card does appear + setTimeout(function () { + if ( + targetElement.is(':hover') + && parseInt(targetElement.attr('data-awaiting-hover-card'), 10) === timeNow + && $('.hovercard').length === 0 + ) { + openHovercard(targetElement, contactUrl, timeNow); + } + }, 500); + }).on('mouseleave', '.userinfo.hover-card, .wall-item-responses a, .wall-item-bottom .mention a', function (e) { // action when mouse leaves the hover-card + removeAllHovercards(e, new Date().getTime()); }); // if we're hovering a hover card, give it a class, so we don't remove it - $('body').on('mouseover','.hovercard', function(e) { + $body.on('mouseover', '.hovercard', function (e) { $(this).addClass('dont-remove-card'); }); - $('body').on('mouseleave','.hovercard', function(e) { - $(this).removeClass('dont-remove-card'); - $(this).popover("hide"); - }); + $body.on('mouseleave', '.hovercard', function (e) { + $(this).removeClass('dont-remove-card'); + $(this).popover('hide'); + }); }); // End of $(document).ready // removes all hover cards -function removeAllhoverCards(event,priorTo) { +function removeAllHovercards(event, priorTo) { // don't remove hovercards until after 100ms, so user have time to move the cursor to it (which gives it the dont-remove-card class) - setTimeout(function(){ - $.each($('.hovercard'),function(){ - var title = $(this).attr("data-orig-title"); + setTimeout(function () { + $.each($('.hovercard'), function () { + let title = $(this).attr('data-orig-title'); // don't remove card if it was created after removeAllhoverCards() was called - if($(this).data('card-created') < priorTo) { + if ($(this).data('card-created') < priorTo) { // don't remove it if we're hovering it right now! - if(!$(this).hasClass('dont-remove-card')) { - $('[data-hover-card-active="' + $(this).data('card-created') + '"]').removeAttr('data-hover-card-active'); - $(this).popover("hide"); + if (!$(this).hasClass('dont-remove-card')) { + let $handle = $('[data-hover-card-active="' + $(this).data('card-created') + '"]'); + $handle.removeAttr('data-hover-card-active'); + + // Restoring the popover handle title + let title = $handle.attr('data-orig-title'); + $handle.attr({'data-orig-title': '', title: title}); + + $(this).popover('hide'); } } }); - },100); + }, 100); } -// Ajax request to get json contact data -function getContactData(purl, url, actionOnSuccess) { - var postdata = { - mode : 'none', - profileurl : purl, - datatype : 'json', +function openHovercard(targetElement, contactUrl, timeNow) { + // store the title in a data attribute because Bootstrap + // popover destroys the title attribute. + let title = targetElement.attr('title'); + targetElement.attr({'data-orig-title': title, title: ''}); + + // get an additional data atribute if the card is active + targetElement.attr('data-hover-card-active', timeNow); + // get the whole html content of the hover card and + // push it to the bootstrap popover + getHoverCardContent(contactUrl, function (data) { + if (data) { + targetElement.popover({ + html: true, + placement: function () { + // Calculate the placement of the the hovercard (if top or bottom) + // The placement depence on the distance between window top and the element + // which triggers the hover-card + let get_position = $(targetElement).offset().top - $(window).scrollTop(); + if (get_position < 270) { + return 'bottom'; + } + return 'top'; + }, + trigger: 'manual', + template: '', + content: data, + container: 'body', + sanitizeFn: function (content) { + return DOMPurify.sanitize(content) + }, + }).popover('show'); + } + }); +} + +getHoverCardContent.cache = {}; + +function getHoverCardContent(contact_url, callback) { + let postdata = { + url: contact_url, }; // Normalize and clean the profile so we can use a standardized url // as key for the cache - var nurl = cleanContactUrl(purl).normalizeLink(); + let nurl = cleanContactUrl(contact_url).normalizeLink(); - // If the contact is allready in the cache use the cached result instead + // If the contact is already in the cache use the cached result instead // of doing a new ajax request - if(nurl in getContactData.cache) { - setTimeout(function() { actionOnSuccess(getContactData.cache[nurl]); } , 1); + if (nurl in getHoverCardContent.cache) { + callback(getHoverCardContent.cache[nurl]); return; } $.ajax({ - url: url, + url: baseurl + '/contact/hovercard', data: postdata, - dataType: "json", - success: function(data, textStatus, request){ - // Check if the nurl (normalized profile url) is present and store it to the cache - // The nurl will be the identifier in the object - if(data.nurl.length > 0) { - // Test if the contact is allready connected with the user (if url containing - // the expression ("redir/") We will store different cache keys - if((data.url.search("redir/")) >= 0 ) { - var key = data.url; - } else { - var key = data.nurl; - } - getContactData.cache[key] = data; - } - actionOnSuccess(data, url, request); - }, - error: function(data) { - actionOnSuccess(false, data, url); - } - }); -} -getContactData.cache = {}; - -// Get hover-card template data and the contact-data and transform it with -// the help of jSmart. At the end we have full html content of the hovercard -function getHoverCardContent(purl, url, callback) { - // fetch the raw content of the template - getHoverCardTemplate(url, function(stpl) { - var template = unescape(stpl); - - // get the contact data - getContactData (purl, url, function(data) { - if(typeof template != 'undefined') { - // get the hover-card variables - var variables = getHoverCardVariables(data); - var tpl; - - // use friendicas template delimiters instead of - // the original one - jSmart.prototype.left_delimiter = '{{'; - jSmart.prototype.right_delimiter = '}}'; - - // create a new jSmart instant with the raw content - // of the template - var tpl = new jSmart (template); - // insert the variables content into the template content - var HoverCardContent = tpl.fetch(variables); - - callback(HoverCardContent); - } - }); - }); - -// This is interisting. this pice of code ajax request are done asynchron. -// To make it work getHOverCardTemplate() and getHOverCardData have to return it's -// data (no succes handler for each of this). I leave it here, because it could be useful. -// https://lostechies.com/joshuaflanagan/2011/10/20/coordinating-multiple-ajax-requests-with-jquery-when/ -// $.when( -// getHoverCardTemplate(url), -// getContactData (term, url ) -// -// ).done(function(template, profile){ -// if(typeof template != 'undefined') { -// var variables = getHoverCardVariables(profile); -// -// jSmart.prototype.left_delimiter = '{{'; -// jSmart.prototype.right_delimiter = '}}'; -// var tpl = new jSmart (template); -// var html = tpl.fetch(variables); -// -// return html; -// } -// }); -} - - -// Ajax request to get the raw template content -function getHoverCardTemplate (url, callback) { - var postdata = { - mode: 'none', - datatype: 'tpl' - }; - - // Look if we have the template already in the cace, so we don't have - // request it again - if('hovercard' in getHoverCardTemplate.cache) { - setTimeout(function() { callback(getHoverCardTemplate.cache['hovercard']); } , 1); - return; - } - - $.ajax({ - url: url, - data: postdata, - success: function(data, textStatus) { - // write the data in the cache - getHoverCardTemplate.cache['hovercard'] = data; + success: function (data, textStatus, request) { + getHoverCardContent.cache[nurl] = data; callback(data); - } - }).fail(function () {callback([]); }); -} -getHoverCardTemplate.cache = {}; - -// The Variables used for the template -function getHoverCardVariables(object) { - var profile = { - name: object.name, - nick: object.nick, - addr: object.addr, - thumb: object.thumb, - url: object.url, - nurl: object.nurl, - location: object.location, - gender: object.gender, - about: object.about, - network: object.network, - tags: object.tags, - bd: object.bd, - account_type: object.account_type, - actions: object.actions - }; - - var variables = { profile: profile}; - - return variables; + }, + }); } diff --git a/view/theme/frio/templates/event_stream_item.tpl b/view/theme/frio/templates/event_stream_item.tpl index 9264e9d2e..2f2af2732 100644 --- a/view/theme/frio/templates/event_stream_item.tpl +++ b/view/theme/frio/templates/event_stream_item.tpl @@ -27,7 +27,7 @@ {{/if}} - {{$author_name}} + {{$author_name}} {{if $location.map}} {{$location.map nofilter}} diff --git a/view/theme/frio/templates/head.tpl b/view/theme/frio/templates/head.tpl index 287e696cb..f944c80ae 100644 --- a/view/theme/frio/templates/head.tpl +++ b/view/theme/frio/templates/head.tpl @@ -75,7 +75,6 @@ - diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index 4b515efcd..a2b5106a6 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -285,7 +285,7 @@ - + {2} {3} diff --git a/view/theme/frio/templates/notify.tpl b/view/theme/frio/templates/notify.tpl index a42647cff..58f3b0da9 100644 --- a/view/theme/frio/templates/notify.tpl +++ b/view/theme/frio/templates/notify.tpl @@ -1,7 +1,7 @@ - + diff --git a/view/theme/frio/templates/photo_item.tpl b/view/theme/frio/templates/photo_item.tpl index 935e6288b..54eb3c1d4 100644 --- a/view/theme/frio/templates/photo_item.tpl +++ b/view/theme/frio/templates/photo_item.tpl @@ -21,7 +21,7 @@ {{* avatar picture *}} - + @@ -33,7 +33,7 @@ {{* the header with the comment author name *}} - {{$name}} + {{$name}} diff --git a/view/theme/frio/templates/search_item.tpl b/view/theme/frio/templates/search_item.tpl index 7f3c0936d..6c2b81516 100644 --- a/view/theme/frio/templates/search_item.tpl +++ b/view/theme/frio/templates/search_item.tpl @@ -74,14 +74,14 @@ {{* The avatar picture and the photo-menu *}} - + - + @@ -91,10 +91,22 @@ {{* contact info header*}} - - {{$item.name}} - {{if $item.owner_url}}{{$item.via}} {{$item.owner_name}}{{/if}} - {{if $item.lock}} {{/if}} + + + + {{$item.name}} + + {{if $item.owner_url}} + {{$item.via}} + + {{$item.owner_name}} + + {{/if}} + {{if $item.lock}} + + + + {{/if}} @@ -114,7 +126,7 @@ {{* contact info header for smartphones *}} - {{$item.name}} + {{$item.name}} {{$item.ago}} {{if $item.location}} — ({{$item.location nofilter}}){{/if}} diff --git a/view/theme/frio/templates/wall_thread.tpl b/view/theme/frio/templates/wall_thread.tpl index 5a10a0255..631aad3be 100644 --- a/view/theme/frio/templates/wall_thread.tpl +++ b/view/theme/frio/templates/wall_thread.tpl @@ -159,14 +159,14 @@ as the value of $top_child_total (this is done at the end of this file) {{if $item.thread_level==1}} - + - + @@ -187,7 +187,7 @@ as the value of $top_child_total (this is done at the end of this file) {{* The avatar picture for comments *}} {{if $item.thread_level!=1}} - + @@ -201,9 +201,21 @@ as the value of $top_child_total (this is done at the end of this file) {{* contact info header*}} {{if $item.thread_level==1}} - {{$item.name}} - {{if $item.owner_url}}{{$item.via}} {{$item.owner_name}}{{/if}} - {{if $item.lock}} {{/if}} + + + {{$item.name}} + + {{if $item.owner_url}} + {{$item.via}} + + {{$item.owner_name}} + + {{/if}} + {{if $item.lock}} + + + + {{/if}} @@ -232,7 +244,7 @@ as the value of $top_child_total (this is done at the end of this file) {{* contact info header for smartphones *}} - {{$item.name}} + {{$item.name}} {{$item.ago}} @@ -251,7 +263,7 @@ as the value of $top_child_total (this is done at the end of this file) {{*this is the media body for comments - this div must be closed at the end of the file *}} - {{$item.name}} + {{$item.name}} {{$item.ago}}
{{$item.ago}} {{if $item.location}} — ({{$item.location nofilter}}){{/if}}
{{$item.ago}} @@ -251,7 +263,7 @@ as the value of $top_child_total (this is done at the end of this file) {{*this is the media body for comments - this div must be closed at the end of the file *}} - {{$item.name}} + {{$item.name}} {{$item.ago}}