From dc5b1c1f5b7f1e55e539fad3ba03d191b05ecdc2 Mon Sep 17 00:00:00 2001
From: root
+
+
+
+
+
+
+
+
+演示地址:http://fecshop.appfront.fancyecommerce.com/
+
+Fecshop 全称为Fancy ECommerce Shop,是基于php Yii2框架之上开发的一款优秀的开源电商系统,遵循[OSL3.0协议](http://www.oschina.net/question/28_8527),
+截止到2016-12-19号,除了支付部分,其他的基本都已经完成,关注fecshop的
+在等2-3个月,也就是明年2,3月份,版本就可以出来,2017年4,5月份在把手机web
+做一下,预计到明年5月份,后台,pc前台,手机web前台 ,命令控制台 这几个入口
+基本可以完善,多谢大家关注和你们的Star,我会坚持把他写好。
+目前由于项目还没有完成,因此,下载安装只能安装部分代码,
+而且数据库部分没有提供migrate,也就是说,目前fecshop还不可用,
+等代码开发完成,我在整体核对一遍代码,
+然后把文档落实,该项目是开源项目,从事外贸电商6年来,
+用了不少开源电商系统,譬如magento,发现开源框架都有一定
+的诟病,在并发方面差,后期扩展,业务发展后期重构难,
+尤其是现在的移动端的发展,多入口的电商模式占据主流,
+性能方面的要求越来越高,Fecshop采用了nosql和mysql结合的方式,
+关系型表放到mysql中,譬如优惠券,购物车,订单等,
+非关系型数据表(非关系型代表不会出现多表强事务类型操作)
+放到mongodb中,缓存用redis,搜索目前用的是mongodb的FullTextSearch功能,
+支持一些主流语言的分词与搜索,不过目前不支持中文 切词 搜索,
+后期扩展一下用ElasticSearch来进行搜索(ElasticSearch有中文插件,安装后支持中文分词)。
+
+
+作者QQ:2358269014
+
+github: https://github.com/fancyecommerce/yii2_fecshop
+
+[![Latest Stable Version](https://poser.pugx.org/fancyecommerce/fecshop/v/stable)](https://packagist.org/packages/fancyecommerce/fecshop) [![Total Downloads](https://poser.pugx.org/fancyecommerce/fecshop/downloads)](https://packagist.org/packages/fancyecommerce/fecshop) [![Latest Unstable Version](https://poser.pugx.org/fancyecommerce/fecshop/v/unstable)](https://packagist.org/packages/fancyecommerce/fecshop)
+
+**Fecshop文档(撰写中)**:[Fecshop Doc Guide](http://www.fecshop.com/doc/fecshop-guide/cn-1.0/guide-index.html#)
+
+
+
+项目状态:
+
+> 项目已经开始,本项目由Terry筹划,预计到2017-05-01出来第一个正式版本。
+
+
+
+
+
+1、安装Fecsop
+------------
+
+本部分为fecshop的核心代码部分,
+是以yii2扩展的方式制作,因此,您安装入口库包`fecshop app advanced`
+,通过`composer update`, 本部分代码会以依赖包的方式被加载安装。
+
+点击这里,进入[安装 fecshop app advanced](https://github.com/fancyecommerce/yii2_fecshop_app_advanced)
+页面。
+
+2、架构特色
+-----------
+
+架构特色:参看详细介绍:[Fecshop 架构特色](http://www.fecshop.com/doc/fecshop-guide/cn-1.0/guide-fecshop-about-fecshop.html)
+
+中文博客:[yii2 教程](http://www.fancyecommerce.com).
+
+Fecshop 全称为Fancy ECommerce Shop,是一款优秀的开源电商系统,遵循[OSL3.0协议](http://www.oschina.net/question/28_8527),
+目的是为了方便yii2用户快速的
+开发商城,Fecshop作为一款可以持续性发展的商城系统,
+在框架层面有以下特性:
+
+1. 由于商城系统的复杂性,原始的框架MVC结构,显的有点力不从心,Fecshop框架
+加入了[Block层](fecshop-feature-block.md),
+Controller层只负责调度, Model只负责数据库映射,中间的处理逻辑由block来完成,View层
+负责显示,这样各司其职, 以免造成controller文件过于庞大。
+
+2. 加入[独立功能块](fecshop-feature-independent-block.md),有点类似Yii2的Widget,目的是为了让一些侧栏公用块
+可以通过配置的方式
+添加,同时,还可以具有设置缓存的功能,譬如侧栏的产品浏览记录,
+newsletter等独立显示块可能在很多
+页面用到,通过独立功能块可以配置方便的载入。
+
+3. 在Model层的上层加入[服务层Services](fecshop-services-abc.md),这样,Controller,Block,View 层,在原则上
+不能直接调用model,必须通过Services层以及子Services层,然后Services访问各个
+model,组织数据,事务处理等操作,将数据结果返回给上层,这种设计可以方便以后业务
+发展后,进而根据业务特点进行重构,或者以后如果出现新技术,新方式,
+都重构成自己想要的样子,譬如,
+将某个底层由mysql换成mongodb,或者为了应付高并发读写并且多事务性的功能部分,
+进行分库分表的设计方式。
+
+4. Fecshop[ 多模板系统](fecshop-feature-mutil-themes.md),Fecshop设置了多个模板路径,各个模板路径下的文件被加载
+的优先级不同,其中,Fecshop的模板路径下的文件最全面,但是优先级最低,
+,第三方模板路径优先级其次,用户本地模板路径优先级最高,
+用户可以通过
+复制相应路径下的view或者js,css文件到本地模板路径,存在于高优先级
+模板路径的文件会被优先加载,这样用户可以通过多模板系统的原理进行模板的
+制作,同时,不影响Fecshop模板的升级,如果Fecshop view文件升级后被修改,
+那么用户可以比对本地模板文件与升级模板文件的代码的不同,
+复制更改的代码到本地模板路径
+即可。第三方的模板路径的优先级介于本地模板路径和Fecshop
+模板路径之间。
+
+5. [重写机制](fecshop-feature-rewrite.md),Fecshop的功能基本都可以被用户重写,包括servies层,Modules,
+Controller,Block,Views,View Layout,
+以及Js Css Img等,都可以被用户重写,其中 Js,Css,Img,Views,View Layout
+ 是通过多模板
+路径优先级来实现的,其他的是通过配置文件的覆盖更改来实现重写,这样,用户
+就可以很方便重构Fecshop或者第三方的功能和模板。
+
+6. 升级最小化干扰,Fecshop的核心文件是放到vendor/fancyecommerce/fecshop
+路径下面,和第三方扩展,用户二次开发路径完全隔离开,
+Fecshop可以通过composer进行核心功能的升级,用户只需要通过composer升级
+即可。
+
+7. 快速高效,[Fecshop Servises](fecshop-services-abc.md)遵循Yii2的懒加载方式,只初始化使用到的组件服务,
+缓存方面有整页缓存,block部分缓存,动态数据ajax加载等方式,让您的网站快速响应。
+
+8. [Fecshop 多入口模式](fecshop-feature-mutil-entrances.md),分为 appadmin(后台), appfront(PC前端),apphtml5(手机web),
+appserver(手机app服务),appapi(erp,或者其他接口对接),
+不同的业务,不同的设备,进入不同的入口,各个入口共用服务层services,
+但是modules部分独立,这样相互干扰最小,可以相互独立开发。
+
+9. 后台封装化,fec_admin扩展可以快速的实现增删改查类型的表单列表,
+方便用户快速的做增删改查。
+
+鉴于以上特点,您可以下载安装fecshop,然后更改fecshop的模板和功能,扩展自己想要
+的功能,或者安装第三方开发好了的扩展或者模板,来快速的组建起来您的网站。
+
+
diff --git a/app/appadmin/config/appadmin.php b/app/appadmin/config/appadmin.php
new file mode 100644
index 000000000..26952026f
--- /dev/null
+++ b/app/appadmin/config/appadmin.php
@@ -0,0 +1,38 @@
+$modules,
+ /* only config in front web */
+ //'bootstrap' => ['store'],
+ 'components' => [
+ 'user' => [
+ 'identityClass' => 'fecadmin\models\AdminUser',
+ 'enableAutoLogin' => true,
+ ],
+
+ 'errorHandler' => [
+ 'errorAction' => 'fecadmin/error',
+ ],
+
+ 'urlManager' => [
+ 'rules' => [
+ '' => 'fecadmin/index/index',
+ ],
+ ],
+ ],
+ 'params' => [
+ 'appName' => 'appadmin',
+ ],
+];
diff --git a/app/appadmin/config/modules/Catalog.php b/app/appadmin/config/modules/Catalog.php
new file mode 100644
index 000000000..318676591
--- /dev/null
+++ b/app/appadmin/config/modules/Catalog.php
@@ -0,0 +1,14 @@
+ [
+ 'class' => '\fecshop\app\appadmin\modules\Catalog\Module',
+
+ ],
+];
\ No newline at end of file
diff --git a/app/appadmin/config/modules/Cms.php b/app/appadmin/config/modules/Cms.php
new file mode 100644
index 000000000..3c9fda3d7
--- /dev/null
+++ b/app/appadmin/config/modules/Cms.php
@@ -0,0 +1,16 @@
+ [
+ 'class' => '\fecshop\app\appadmin\modules\Cms\Module',
+ 'params'=> [
+
+ ],
+ ],
+];
diff --git a/app/appadmin/config/modules/Customer.php b/app/appadmin/config/modules/Customer.php
new file mode 100644
index 000000000..8748df185
--- /dev/null
+++ b/app/appadmin/config/modules/Customer.php
@@ -0,0 +1,16 @@
+ [
+ 'class' => '\fecshop\app\appadmin\modules\Customer\Module',
+ 'params'=> [
+
+ ],
+ ],
+];
diff --git a/app/appadmin/config/modules/Fecadmin.php b/app/appadmin/config/modules/Fecadmin.php
new file mode 100644
index 000000000..77480ff37
--- /dev/null
+++ b/app/appadmin/config/modules/Fecadmin.php
@@ -0,0 +1,18 @@
+ [
+ 'class' => '\fecadmin\Module',
+ //'controllerMap' => [
+ // 'login' => [
+ // 'class' => 'appadmin\local\fecadmin\controllers\LoginController',
+ // ],
+ //],
+ ],
+];
diff --git a/app/appadmin/config/modules/Sales.php b/app/appadmin/config/modules/Sales.php
new file mode 100644
index 000000000..bcc01a697
--- /dev/null
+++ b/app/appadmin/config/modules/Sales.php
@@ -0,0 +1,16 @@
+ [
+ 'class' => '\fecshop\app\appadmin\modules\Sales\Module',
+ 'params'=> [
+
+ ],
+ ],
+];
diff --git a/app/appadmin/interfaces/base/AppadminbaseBlockEditInterface.php b/app/appadmin/interfaces/base/AppadminbaseBlockEditInterface.php
new file mode 100644
index 000000000..c86de5a56
--- /dev/null
+++ b/app/appadmin/interfaces/base/AppadminbaseBlockEditInterface.php
@@ -0,0 +1,24 @@
+
+ * @since 1.0
+ */
+interface AppadminbaseBlockEditInterface{
+
+ /**
+ * set Service ,like $this->_service = Yii::$service->cms->article;
+ */
+ public function setService();
+ /**
+ * config edit array
+ */
+ public function getEditArr();
+}
\ No newline at end of file
diff --git a/app/appadmin/interfaces/base/AppadminbaseBlockInterface.php b/app/appadmin/interfaces/base/AppadminbaseBlockInterface.php
new file mode 100644
index 000000000..bd37dbbdd
--- /dev/null
+++ b/app/appadmin/interfaces/base/AppadminbaseBlockInterface.php
@@ -0,0 +1,20 @@
+
+ * @since 1.0
+ */
+interface AppadminbaseBlockInterface{
+
+
+ public function getSearchArr();
+ public function getTableFieldArr();
+}
\ No newline at end of file
diff --git a/app/appadmin/modules/AppadminbaseBlock.php b/app/appadmin/modules/AppadminbaseBlock.php
new file mode 100644
index 000000000..ba0914f33
--- /dev/null
+++ b/app/appadmin/modules/AppadminbaseBlock.php
@@ -0,0 +1,619 @@
+
+ * @since 1.0
+ */
+class AppadminbaseBlock extends Object{
+ /**
+ * parameter storage front passed.
+ */
+ public $_param = [];
+ /**
+ * fecshop service
+ */
+ public $_service;
+ /**
+ * default pages number
+ */
+ public $_pageNum = 1;
+ /**
+ * collection default number displayed.
+ */
+ public $_numPerPage = 50;
+ /**
+ * collection primary key.
+ */
+ public $_primaryKey ;
+
+ /**
+ * collection sort direction , the default value is 'desc'.
+ */
+ public $_sortDirection = 'desc';
+ /**
+ * collection sort field , the default value is primary key.
+ */
+ public $_orderField ;
+
+ public $_asArray = true;
+ /**
+ * current url with param,like http://xxx.com?p=3&sort=desc
+ */
+ public $_currentParamUrl;
+ /**
+ * current url with no param,like http://xxx.com
+ */
+ public $_currentUrlKey;
+ /**
+ * data edit url, if you not set value ,it will be equal to current url.
+ */
+ public $_editUrl;
+ /**
+ * data delete url, if you not set value ,it will be equal to current url.
+ */
+ public $_deleteUrl;
+ public $_currentUrl;
+
+
+ /**
+ * it will be execute during initialization ,the following object variables will be initialize.
+ * $_primaryKey , $_param , $_currentUrl ,
+ * $_currentParamUrl , $_addUrl , $_editUrl,
+ * $_deleteUrl.
+ */
+ public function init(){
+ if(!($this instanceof AppadminbaseBlockInterface)){
+ echo 'Managere must implements fecshop\app\appadmin\interfaces\base\AppadminbaseBlockInterface';
+ exit;
+ }
+ $param = \fec\helpers\CRequest::param();
+ $this->_primaryKey = $this->_service->getPrimaryKey();
+ if(empty($param['pageNum'])) $param['pageNum'] = $this->_pageNum ;
+ if(empty($param['numPerPage'])) $param['numPerPage'] = $this->_numPerPage ;
+ if(empty($param['orderField'])) $param['orderField'] = $this->_primaryKey ;
+ if(empty($param['orderDirection'])) $param['orderDirection'] = $this->_sortDirection ;
+ if(is_array($param) && !empty($param)){
+ $this->_param = array_merge($this->_param, $param) ;
+ }
+ $currentUrl = CUrl::getCurrentUrlNoParam();
+ $this->_currentParamUrl = CUrl::getCurrentUrl();
+ $this->_editUrl = $this->_editUrl ? $this->_editUrl : $currentUrl;
+ $this->_deleteUrl = $this->_deleteUrl ? $this->_deleteUrl : $currentUrl;
+ }
+
+ /**
+ * generate pager form html, it is important to j-ui js framework, which will storage current request param as hidden way.
+ * @return $str|String , html format string.
+ */
+ public function getPagerForm(){
+ $str = "";
+ if(is_array($this->_param) && !empty($this->_param)){
+ foreach($this->_param as $k=>$v){
+ if($k != "_csrf"){
+ $str .='';
+ }
+ }
+ }
+ return $str;
+ }
+
+ /**
+ * @property $data|Array, it was return by defined function getSearchArr();
+ * generate search section html,
+ */
+ public function getSearchBarHtml($data){
+ if(is_array($data) && !empty($data)){
+ $r_data = [];
+ $i = 0;
+ foreach($data as $k=>$d){
+ $type11 = $d['type'];
+ if($type11 == 'select'){
+ $value = $d['value'];
+ $name = $d['name'];
+ $title = $d['title'];
+ $d['value'] = $this->getSearchBarSelectHtml($name,$value,$title);
+ }else if($type11 == 'chosen_select'){
+ $i++;
+ $value = $d['value'];
+ $name = $d['name'];
+ $title = $d['title'];
+ $d['value'] = $this->getSearchBarChosenSelectHtml($name,$value,$title,$i);
+ }
+ $r_data[$k] = $d;
+ }
+ }
+ $searchBar = $this->getDbSearchBarHtml($r_data);
+ return $searchBar;
+ }
+
+ /**
+ * @property $name|String , html code select name.
+ * @property $data|Array, select options key and value.
+ * @property $title|String , select title , as select default display.
+ * generate html select code .
+ * @return String, select html code.
+ */
+ public function getSearchBarSelectHtml($name,$data,$title){
+ if(is_array($data) && !empty($data)){
+ $html_chosen_select = '';
+ return $html_chosen_select;
+ }else{
+ return '';
+ }
+ }
+ /**
+ * @property $name|String , html code select name.
+ * @property $data|Array, select options key and value.
+ * @property $title|String , select title , as select default display.
+ * @property $id|Int , use for chosen select config, if you use this function muilt times , $id must be unique in each time
+ * for example ,first time use this function set $id = 1, next time ,you can set $id=2,because is must be unique in front html.
+ * generate html select code .
+ * @return String, chosen select html code.
+ */
+ public function getSearchBarChosenSelectHtml($name,$data,$title,$id=1){
+ if(is_array($data) && !empty($data)){
+
+ $html_chosen_select .= '
+ ';
+ $html_chosen_select .= '';
+ return $html_chosen_select;
+ }else{
+ return '';
+ }
+ }
+ /**
+ * custom html code at the end of Search Bar.
+ * your can rewrite this function in your block class.
+ */
+ public function customSearchBarHtml(){
+ return '';
+ }
+
+ /**
+ * @property $data|Array
+ */
+ public function getDbSearchBarHtml($data){
+ $searchBar = '';
+ if(!empty($data)){
+ $searchBar .= '';
+ $searchBar .='
+
+ ';
+ foreach($data as $d){
+ $type = $d['type'];
+ $name = $d['name'];
+ $title = $d['title'];
+ $value = $d['value'];
+ if($d['type'] == 'select'){
+ $searchBar .= '
+
+ '.$value.'
+ ';
+ }else if($d['type'] == 'chosen_select'){
+ $searchBar .= '
+ '.$value.'
+ ';
+ }else if($d['type'] == 'inputtext'){
+ $searchBar .= '
+ '.$title.':
+ ';
+ }else if($d['type'] == 'inputdate'){
+ $searchBar .= '
+ '.$title.'
+ ';
+ }else if($d['type'] == 'inputdatefilter'){
+ $value = $d['value'];
+ if(is_array($value)){
+ foreach($value as $t=>$title){
+ $searchBar .= '
+ '.$title.'
+ ';
+ }
+ }
+ }else if($d['type'] == 'inputfilter'){
+ $value = $d['value'];
+ if(is_array($value)){
+ foreach($value as $t=>$title){
+ $searchBar .= '
+ '.$title.'
+ ';
+ }
+ }
+ }
+ }
+ $customSearchHtml = $this->customSearchBarHtml();
+ $searchBar .= $customSearchHtml;
+ $searchBar .= '
+
+ ';
+ $str .= ' ';
+ return $str;
+ }
+
+ public function getTableTheadArrInit($table_columns){
+
+ foreach($table_columns as $field){
+ $d = [
+ 'orderField' => $field['orderField'],
+ // 'label' => $this->_obj->getAttributeLabel($field['orderField']) ,
+ 'width' => $field['width'],
+ 'align' => $field['align'],
+ ];
+ $d['label'] = $field['label'] ? $field['label'] : '';
+ if(empty($d['label'] )){
+ $d['label'] = $field['orderField'];
+ }
+ $table_th_bar[] = $d;
+ }
+ return $table_th_bar;
+
+ }
+
+ /**
+ * list table body.
+ */
+ public function getTableTbody(){
+ $searchArr = $this->getSearchArr();
+ if(is_array($searchArr) && !empty($searchArr)){
+ $where = $this->initDataWhere($searchArr);
+ }
+ $filter = [
+ 'numPerPage' => $this->_param['numPerPage'],
+ 'pageNum' => $this->_param['pageNum'],
+ 'orderBy' => [$this->_param['orderField'] => (($this->_param['orderDirection'] == 'asc') ? SORT_ASC : SORT_DESC )],
+ 'where' => $where,
+ 'asArray' => $this->_asArray,
+ ];
+ $coll = $this->_service->coll($filter );
+ $data = $coll['coll'];
+ $this->_param['numCount'] = $coll['count'];
+ return $this->getTableTbodyHtml($data);
+ }
+
+ public function getTableTbodyHtml($data){
+ $fileds = $this->getTableFieldArr();
+ $str .= '';
+ $csrfString = \fec\helpers\CRequest::getCsrfString();
+ foreach($data as $one){
+ $str .= '';
+ foreach($table_th_bar as $b){
+ $width = $b['width'];
+ $label = $b['label'];
+ $orderField = $b['orderField'];
+ $class = isset($b['class']) ? $b['class'] : '';
+ $align = isset($b['align']) ? 'align="'.$b['align'].'"' : '';
+ $str .= ' '.$label.' ';
+ }
+ $str .= '编辑 ';
+ $str .= '';
+ $str .= ' ';
+ }
+ return $str ;
+
+ }
+
+ /*
+ example : getTableFieldArr
+ detail refer function getTableTbodyHtml($data)。
+ public function getTableFieldArr(){
+ $table_th_bar = [
+ [
+ 'orderField' => '_id', # db columns
+ 'label' => 'ID', # db columns display in table head
+ 'width' => '40', # columns width in table list
+ 'align' => 'center',# columns position in table list td
+
+ ],
+ [
+ 'orderField' => 'keyword',
+ 'label' => '关键字',
+ 'width' => '110',
+ 'align' => 'left',
+ ],
+ # select 选择类型 display 对应的是一个数组,通过key 对应值
+ # 一般是状态,譬如 1 对应激活,2对应关闭等。
+ [
+ 'orderField' => 'unit',
+ 'label' => '站点',
+ 'width' => '110',
+ 'align' => 'left',
+ 'display' => CConfig::param("channel_type"), # Array
+ ],
+ # 图片类型:
+ [
+ 'orderField' => 'img',
+ 'label' => '图片',
+ 'width' => '110',
+ 'align' => 'left',
+ 'convert' => ['string' => 'img'],
+ 'img_width' => '100', # 图片宽度
+ 'img_height' => '100', # 图片高度
+ ],
+ [
+ 'orderField' => 'created_at',
+ 'label' => '创建时间',
+ 'width' => '190',
+ 'align' => 'center',
+ //'convert' => ['datetime' =>'date'],
+ # 把 datetime(Y-m-d H:i:s) 转化成datetime(Y-m-d)
+ ],
+
+ [
+ 'orderField' => 'updated_at',
+ 'label' => '更新时间',
+ 'width' => '190',
+ 'align' => 'center',
+ 'convert' => ['datetime' =>'date'], # int date datetime 显示的转换
+ ],
+ [
+ 'orderField' => 'updated_at',
+ 'label' => '更新时间',
+ 'width' => '190',
+ 'align' => 'center',
+ 'convert' => ['datetime' =>'int'], # datetime格式转换成时间戳
+ ],
+ ];
+ return $table_th_bar ;
+ }
+ */
+}
\ No newline at end of file
diff --git a/app/appadmin/modules/AppadminbaseBlockEdit.php b/app/appadmin/modules/AppadminbaseBlockEdit.php
new file mode 100644
index 000000000..4645bf2c1
--- /dev/null
+++ b/app/appadmin/modules/AppadminbaseBlockEdit.php
@@ -0,0 +1,253 @@
+
+ * @since 1.0
+ */
+class AppadminbaseBlockEdit extends Object{
+
+ public $_param;
+ public $_primaryKey;
+ public $_one;
+ public $_service;
+ public $_textareas;
+ public $_lang_attr;
+ /**
+ * html input or text etc. , html name like:
+ */
+ protected $_editFormData;
+
+ public function init(){
+ if(!($this instanceof AppadminbaseBlockEditInterface)){
+ echo json_encode(array(
+ 'statusCode'=>'300',
+ 'message'=>'Manageredit must implements fecshop\app\appadmin\interfaces\base\AppadminbaseBlockEditInterface',
+ ));
+ exit;
+ }
+ $this->_editFormData = 'editFormData';
+ $this->setService();
+ $this->_param = CRequest::param();
+ $this->_primaryKey = $this->_service->getPrimaryKey();
+ $id = $this->_param[$this->_primaryKey];
+
+ $this->_one = $this->_service->getByPrimaryKey($id);
+ }
+
+
+ public function getEditBar($editArr=[]){
+ $langs = Yii::$service->fecshoplang->getAllLangCode();
+ $defaultLangCode = Yii::$service->fecshoplang->defaultLangCode;
+ if(empty($editArr)){
+ $editArr = $this->getEditArr();
+ }
+ $str = '';
+ $langAndTextarea = '';
+ if($this->_param[$this->_primaryKey]){
+ $str = <<';
+ foreach($fileds as $field){
+ $orderField = $field['orderField'];
+ $display = $field['display'];
+ $val = $one[$orderField];
+ $display_title = '';
+ if($val){
+ if(isset($field['display']) && !empty($field['display'])){
+ $display = $field['display'];
+ $val = $display[$val] ? $display[$val] : $val;
+ $display_title = $val;
+ }
+ if(isset($field['convert']) && !empty($field['convert'])){
+ $convert = $field['convert'];
+ foreach($convert as $origin =>$to){
+ if(strstr($origin,'mongodate')){
+ if(isset($val->sec)){
+ $timestramp = $val->sec;
+ if($to == 'date'){
+ $val = date('Y-m-d',$timestramp);
+ }else if($to == 'datetime'){
+ $val = date('Y-m-d H:i:s',$timestramp);
+ }else if($to == 'int'){
+ $val = $timestramp;
+ }
+ $display_title = $val;
+ }
+ }else if(strstr($origin,'date')){
+ if($to == 'date'){
+ $val = date('Y-m-d',strtotime($val));
+ }else if($to == 'datetime'){
+ $val = date('Y-m-d H:i:s',strtotime($val));
+ }else if($to == 'int'){
+ $val = strtotime($val);
+ }
+ $display_title = $val;
+ }else if($origin == 'int'){
+ if($to == 'date'){
+ $val = date('Y-m-d',$val);
+ }else if($to == 'datetime'){
+ $val = date('Y-m-d H:i:s',$val);
+ }else if($to == 'int'){
+ $val = $val;
+ }
+ $display_title = $val;
+ }else if($origin == 'string'){
+ if($to == 'img'){
+
+ $t_width = isset($field['img_width']) ? $field['img_width'] : '100';
+ $t_height = isset($field['img_height']) ? $field['img_height'] : '100';
+ $val = '';;
+ }
+ }
+ }
+ }
+ if(isset($field['lang']) && !empty($field['lang'])){
+
+ $val = Yii::$service->fecshoplang->getDefaultLangAttrVal($val,$orderField);
+ }
+ }
+ $str .= ' '.$val.' ';
+ }
+ $str .= '
+ 编辑
+ 删除
+ ';
+ $str .= '
+ {$tabLangTitle}
+
+
+ '.$value.' + | '; + }else if($d['type'] == 'chosen_select'){ + $searchBar .= '+ '.$value.' + | '; + }else if($d['type'] == 'inputtext'){ + $searchBar .= '+ '.$title.': + | '; + }else if($d['type'] == 'inputdate'){ + $searchBar .= '+ '.$title.' + | '; + }else if($d['type'] == 'inputdatefilter'){ + $value = $d['value']; + if(is_array($value)){ + foreach($value as $t=>$title){ + $searchBar .= '+ '.$title.' + | '; + } + } + }else if($d['type'] == 'inputfilter'){ + $value = $d['value']; + if(is_array($value)){ + foreach($value as $t=>$title){ + $searchBar .= '+ '.$title.' + | '; + } + } + } + } + $customSearchHtml = $this->customSearchBarHtml(); + $searchBar .= $customSearchHtml; + $searchBar .= '
'.$label.' | '; + + $str .= 'sku | qty | price | img | delete | '; + $this->_custom_option_list_str .= '
---|---|---|---|---|---|
图片 | +label | +sort_order | +主图 | +删除 | +
+ | + | + | + | 删除 | +
+ | + | + | + | 删除 | +
+ + + + + + + + +
++ + + + + + + +
+Title | +Is_Required | +Sort_Order | +
+ | + | + |
zPp+BG^AVOrYecHqbA3_}wL1=w(^Q|Ibo_jYARo}KA&ia*@K4+gIu4)xz5khMwzpQV z6B0Jwv#IdYJbJR4g`SDI61K1R&BiAcIk?=|(-)`j-DtJgaV>oIrB~nC$ON&y^U|5$ zY@Xln34l>qGgBu|MM#6l#-~DFe3}HAPe!0X{dB|}*gX#qctcVwnG0n>IO|m1VrS=> zVTk}UD<>@28JbWlfq+zPp}A-CbR3D>9~SQTV|~&+@)bU&A5TJ=Yj8-}2odMIzaXCO z?H)advwbtkF7W^awH2QrTr0l?R$JMa7|gV=B*@BIpvWR# c_yH>0})$aMlsoC3NCA*6@ZUD~yJU zN(GeWIsgUIT4W;p6?V6x)cGrk3Nst86YOnpnofq!?0hVs*v1ItZHEmP?SkE@=r|s~ z@?
lV`JZ=L`;=LEH4(8TYv(T3TRR`T|Dzx@6j zw!Wi%+!nwS$qzPIA@IPn3bNJ+4sYk2z1_HNZOYWl+h=fLTV4P0bAVcS(bzxo;W3Z% ry)Jw7DYvO4SF4>*yP8|Nl0ENR<%sdO+uAqfkZUyPg>8oVIQPE+iI=;0 literal 0 HcmV?d00001 diff --git a/app/appfront/theme/base/front/assets/fancybox/fancybox_overlay.png b/app/appfront/theme/base/front/assets/fancybox/fancybox_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..a4391396a9d6b6d7ff3b781f16904732fea40bdd GIT binary patch literal 1003 zcmbVLJ8#oa7&R(Fs8R<|7ht(^mx74x>m;si#gzIH8i|xBjnr(^v2PlywXeCpY1~YR z4GEC=56mo#2*Jw43=>F U4RxdEX3ZEcpdS z%HtH+f>7JeQ$IK+9QDXilvv`=x9>$1g_d|wZ7R*wA%kdl%*g(DuM>=q10xi-@1R<4 zf DLYHJ zpO=zsW3J$mEMQT}BbuN>(eKeAw?y!C8bX{ln+xG2n zt)TZj+1-SpfCuZ_LS%yYmedK=8(Vz#=G$f8x?$7?XrITuX#MQW%A%tvGr` zFWZLWl|78Hj`gbN7+aoWS6m%?bB$%(y6YLbXFEz+)iCx{LpKc9Q9w#{@K$BPZ6q1@ zlYq?aMqqcwwa?|64kJFNtV8L^yaQST%4s&BDRTBTw0RIEAsuBmi}FmPbqR}3Nmyqz zMw9%S(GvSM{#V>nZumbrlffCeXpX;{Wqt)6SZo)q4~NC@kOU@%!DzfWy>bD@>PExe v>EvH}>tDZp{&4r=VGmt>cI(v(`?0Vh3| 0{{R3r~&&>0002JP)t-s00000 z0000001gfg00000000000L{(K0RaKo+1UdF0|y5O0002r-`@fP0zW@L0RaI3004r5 zf*c$i<>lo7006(gzwz<$1_lOaXJ-Ha0PO7S1_lQB`1n6RKgr3-o}Qj(XJ_~K_k)9j z0002c(9rn!_^z(5+S=Ou{QT_f>;M1&`T6<%{r%qF-T(jq|Ns9^PENtW!8J8CtgNh! zjg6d~oO*hCU0q#hXlN`fEV{b7A|fKr&dxzWL2cadjQ{`uFLY8)Qvd-22n`Y$9U~_# zIz&iQRb6RmY;AdZe}{>XmZ71nva`0nz{Sba)ZXIw`TG6+j4$gO000CPNkl 2x46b6u4*Y}3asYn+5i8uzL!nR%M6xSwKsc_zR;VeIz1!l=7%bc z^y9i1)H)rlQX5H}t{Ws>?{u#6gz84u?!QbIi|O0XJDu=rsP(kOm!=PlH`(sv9EkSo zO_FTZdqMae(=to80;1R*KD8?Z-XAW}75f}vpB-w-_K1jXvbyyskRKG~i0)Nd)AX*h zM0#jwkEyO{im};yhRB-mZUqXW7+c;F1v9Jy3$|wC<2h!|U! Lx#xcXj0@L!j8|xED11W*crqOmmrm2 zaNL9`2D5c~he(BkB@$-KlIa8s8Kwh<=ae59U)>sWI-q=Y6CBUZC4Z4p^bJjdEssKP z4;QpSWa-4pp=U@h!6|;59SN>-kagZYW2)i=R-w zJ=+`1BBWbJw<+SWZLl#Hfl2g80BLcm$WxI5;@LL23}o63Dsxiw@i}&xZ5D^)2ZPC6 zfF$O#{~XJ>Qc0%mc*K(e-*aq}>#IqVxoO!wht#tzlWY}M#i?*j5|wTPZQ{iL5x038 z-$MSyrrbCx`a?Ami??6*t($WH7UQh wE<)u58NP6v$8fC?65` z4W?!G9jiornqN$vX@>O$Qnk$2K;L9 5zzM*yo_XfmGCZ#pXchx2 z{#7tioQ*#A7036HeWemZIWsM6L^)Vu!zsc6-G;m=zuCI31o0^Nyk`#m7+u_-6yeZ6 z?*v!*7}4p{qP%j7+6%`VB5APEs4^y4U5O=7NO@C4lVRYnF{keNA#nVMHsVYJ!D@Ek=a*;C*@) zB>N!DUaBTuFWl_Be62iev6No9S=(}GxLDcS>f2hqLLmojACj15G*pxf{C@43`=`?V z{B&<<*imdxkW}1CXP`!1$fOD)ShbO?RGVh9hWkinW?gC)41$#k#Vcbndduex2j6%} z5<3@|rleEhTHyz%DHf7yswkqQTLB0*Il0^N(%ZuJ>m@U}CG($h@woom=ggb?+uL`e zQkF~CazPynEH`B2Azv1~9LDpZ#jr6!ELJQ8b`_#40zdQK+jS)u0vlj7$;R3lM<^Dv z)7PqfqZ0#m@(87$#tkOr-*`w;jyBlhk0c#;D1`vWDFCDlLg`hyVfZO-Pl3pV=6nW* zv?+5cC=r*66cEI8BS_50V_J`uawj~QcxkKKku8Ypv)Fl6$ciTxC)OP`eoxRnPE8Z? zH{Lm+b)wo%K?ui01)JxXFE501S;AqBErh(nXaGdnNbr`N>m5;d)MSTM7`5`H|CD`> zm{WI>-XQh%;I+c0({i2d#L#j*S0c{wKz@iUiCA8b3N_0@lik2e)yD1`t1v1hJUta^ zDBXi$UOxUw`$N`yvR3^?oz%h7(eE ~?0Nx2MO&NlFCFYspYH)r`WW*qG;?IIcuiD%7d~ZFNWkt4>a^p+tU8Bjxa+ z!ll`Vh8b~E`#%R-IZKUe@2_Q=hZXB@=1l}mdB`#xZKAlMxico>(iZH^uOId3?)~G- zIoWE1x|44-=FDH8|7@uI9WMXMVLvGWgIj}%VIr${#nF%`#IJB@I>`EFp1*UPdfzWq zJ$SL6)+cBZw<;c!s}YysIkRCbb*{IDeZRj#P<}GPvGUZ0=w*lZuQSW(%Y#Gg_E3B0 z9Ii=|I3}GHG-eI_WVXFl5_*K6%BOQeX!6VW(ly0q36 cQ5yo(2xlTzsVY&T1V^B4{QhNDrNhYw8v+|C*QK^{#mTglg)5!TGTYd}8k zon&GUIv?jX;>Ua))v6QiBp?f$2flYu6@1BHDd!XChgnEZe47CDWBkq`Bo;6fR-sjY z^5(B++W25Qi@CdaFE#ARdx!S*Q~s2qCjr2Cru*0hy%iYa^4wEAaTO~4Zi7UoC5~&z zN3*!aeC7%+HTlyb6P0H+QU$E>%re!nA5(SzOn=G!mj7w4V0vh(oAV0EQ!9Pt?$Nb7 z^Vx5r?UE>-RjWGefL+RdpE?SpiHh5h)7qqyVWQiX9!5@KddB`z*%KQTR WF(?ZKz0zi~= IeBa&aki8 6l$I-35q6TB$P6YCpB1> zW0gv&Fx(L-{Wk&J{4=-rq6eXi?6Ps3$p@)u1kPd0C7%qq7%I4j3bv<*W|~(X3GJU` zEy}O?f9I(Rlq(=M{}i3A^}}I3q-JUrSE^BQRBy%g5Svjm;IRiExH!>4dyLL2HlnX9 z?(f$6USpU2Yu@6K4er@bl5QV$_sY8*Vorm5oRZi@aHZBs-E&7y{%AHWqE&gFJLMVB zlj8Nut7#b@owUx(M_I*EgX?h6pRL&0C5xAj7vu0BX+;|okj L z>!;@{QO0A#7nkLx?iB@Q8cDC+Iytdxu@MUP8Ih;}gxO#zkK9FSO^5mx6Oa9wPNlA& z;>?w8{pRKCbw3a5pNXFLTOU{DXZxNOTXXZG{n{^vbUGd>nLBELh3WjEjNgt7G4fyG zu4An&U6MA7<{c
P>K~WSV?Q iOUg(!Dd1dWv0J@ GIAL)h*?aeE#ulO zk|BhCPH)43#Mp`=Bf0xHCiYY{;2@sygM5xXMzZ%K92->{{Z|j(x?YBs5pATq*L&*r z8$-QkBs%oFGZ 1E zS`=@;rpDhdTu)kBxE`@XVMZOqRx+hEt1E(U+scqDrXACRk4X3mLI5>h!%J-zA`=aW zSGbs*ZzFPLxt8_W8Sx2(W)|PWl&rpYY0#|um@d^SJTV$U^CFmI$lv;tFu14AEZklZ zzJVmGv3u`7>k!O-@_cQuIZ%gpuQ+pgtzg~2_>JkkG_|jQ(#~q^uL~|{wjMe(Fzho6 zBb;2MMEWZG?xua1muK@9h7r554RN<$xn>es!t^=ks!~q6voxbz#ozRgL+n{8#Cf =LK1}?L?PGipU>sa z5>)yHF4R*C`{Dq)ho{B2uWQ?$+FECBTrofb+*{ y3xD&a?~N;?BV*)klj7{gr*Rb z3zRa#*zWc+tT! gB#B!bV1-Grf1Z^lFE-pmJU(_sf^>uymMAXgN1@`#1; ze&uuY_Czmy32YL6nG8wkrvSWIFZ9`K+L8KE4x`lHREkN96+(UskQ#`m(JC8#p@k_h ztrFe|Pw3lA`2(v@3ocXtAS9EGdegUP*?yaEZD#K+SkP%o;Dj%9_pzkDk6UHv;@m#h z(ek%E1X4Laemh2;T~ch3b+NPDVdGOs$p3kud2CVlG{x`Sm$*@O9?_n-%A!$BAHnnR zwvp+nMD&ZY1!FE#V8amjJj?Oj?9*FhPp-To`@bYL(Kn8qw9^#x*cGvck6OkEo|Mu= zf$1Je=xGT>@L5ljNQkiCe-cl53FATYs}{62m7Vn59vqn01}#~ (BWRG)gz{&;{B zhV4J MP>f)s7Po63UrFw*J42u$*sY;S6 z5p@_fM(slvZGq~1>`3QH>MsTd9jdL?E%V~jRhoTf=;55#BSvEWF%Ac2$OpQvtk<+C z{95iP22@5lt?Rl|g9-M}H0^X$@4Nlid~K2zi1ZC1Ar}EUis9!Pb!?q9H7tuefW_FW zmqv#`QpP3{CxMaIv` t?e zcw11XtJZ?%hu@fVFdP&sV&I$Iq&}6Y{>$a=j1X^TiE)e4z>}YhEKTJr2`+|dpCa># zs8);fZ|#G(rY4?BGvI|M(+MT9B6<8Zgs}rxJZ&$(D4Z+W@~&f-DYgB2ME>E^qgTNu z*<5SZFG7ez7Ym7EfjzDOM8)zVl{F60*)?in+)6Q5Dj)ps-|yKL2lLvmwI(V#!6ae` zWnX%&-F_?)^T%N$+{$IF!h@uCS&swPs4EIH;i?URX6Fa5m+yK7wR|TFlA&)&8o_jV zDTOAl9GzEAs>*RREaP>j8I AD_HfeICPI*5)|7?>i%V-`{-(&{_k39%&gW zo$16PZH!PZMHbXaTSo _t({|xh+<}hxwhQZb2P{! f#O`tfYF2Rj(P|c3g#K)H2ypvsZ@9GF&<5HT5)CTU0M&1@tauT zxlk(W^<{aF)1!N@=DLeBHXe6}+k&2E96!T%44{`bWJn2fu_KsNqI5l6u7CmDdyvz< zk*Hqyk*0`jFyNU2J;q5ZtSePbQ}H0{Z2fAVwA=#RoB3@du%Lz3QS<1U$)ma+HE(`3 zQIhnhQ(NBa?ysA^XwBO}&@U;=ql1GzHOlp|#}iV{6 $L#OS;gS;DXkCYiju*z`N zuw8kOKg=TfdfTL&oUsVLHmI$Bw^{xpxMjj4%H-xI#i(*;fPX8sA}qTdyKFrr>c!(v z!P~R#-#oczrNJt#Tdg+1SF>3LtEDmUQBg#8%0D8SsQj(Z;uoSxA79$6Q;k;S0* w&_cj@-Qs@$G|9ky?Oey7=20!DG zD_M2$wQ| stoVX9l10-&_UZAbBwGm;1+ ze}l8!FIrmj70ZyqifJ|{M!FzM9Kr5h6y8GwIv%BcU)c9HT(Yw*Q?xi2rJUvwHP5Tx z2Uc@Te-4Z^5Qq@X5YDl{#KxGBFn%5L#tq@U{Jly2SKEt)3f}zl276=I<;DQjb;bII z7>=kYX4eAu&Zm?}vvHb+b?s?WlClzkWIcOzIiW^r(A1oO=fsQj^p2Ju>fqi%oGJr< z=DPrCJX}m{;wqxWwXxw!`g!~H=jzmyvI3$}N(4DUoCa-gO6GRhwYep8Q7TlTkGH`+ zA3mTX5zLs4Z9|u0*l-ncUHI7jmV!T08p-Xesj@YE!pUgp!`0RHR21Cne)BB9dzxhS zQKY(umEHw(p0EUuoN2r#tHgg0l%ukPwNknrp4O eB%`X- zqM%;a{Jw9@kpEsLAbv`VO+l_I>g&CQ65Ax3NDu=`CUe^(ivCd|`w@Ie;Nz{fZ{Kur zcy`L}>kPTFZGJ%{8VjTaR)Kw)(f{z8_!ob>U)vg$){*%mObM{&)t}vGEi6{;pZBxu z4iL(}RDMhuAuI;r$3$PQ2!z(DoLl%Xk;|>7A5l9zmAk;b)!vH6X1wD<`TuR{=Hu-4 zNv=m$_?b&*AM0&I6pe=)FsTS&y$YKy ~XOgKVVnB( F3oa>|jtRW#?W{JEP@c)9 qpcy7~BYnCW&Kw~Yz62|BTHwX6+;CklwaE^2p=-)+ZCOO^!`JWa%CDI-Px5F{A zi~`Qd(A|D>X 0j5Kr;^=1MqU9@fn&ABSNO5@V09QkW=epK$cbPVY-eEv^D%9ls z)=h6p99=_e83xZTF&iUroj(xLK;o}=4ubBgtd=Z5or*I*8&0aKK~E@($$yto3g&pc zOHZVX0~9 9aNM>Y?kMkUhTJuu2LK-{tm1mu32m%7}SH`5SwGp=(FzOuV_$A2N~E zT1!%5*$TcvNx@vF#DY5|-ZMASLa!z~A2#*mPwA$1q%*y5XXk~z!Vq4+mi&L@i1=VR zmjkR%?wW>U5}urjk;=mis1_0vdN%qClrLUpK5ntoc5Ve&8*fiOx^7N~384=0Z5_`? zj3nl=7MO7^O9LyypVtop@~J(d5>9Qk>b yP#}Hd8ZYz9ahK^a2(Q*y<~&fsQ!`BT;OzkD?(~jc z5F#@X%l4=1;?T>8TgQ$(6Ht1M52=Z=tIcDEjz4x;EcE1!-|L{8<&5NeNxIzZFFd(M zw&c}B%=vB(`}-Gd3RPUGU40LULVDrk8TKsHRk?cK;<6S+b;ZuiY+7KH{OR#xo(Lm2 zcyj3O5soRhN3lSf 9No1QjB@{nBpektQqZ@$Whb=4EIR8X7Y1@IUq z;4@>7-Ak-U7 0Z>;B$EHC z`BqhJp@!B&%oK4yh9HXaibXtJgRKijubV=Ze^A*5f;X%nH#0=vSNcXk zU-48)jQj59@e|M_L%$Cdfq+>j0bE1b*HJF*gY?~+ZUqKtt7f7meA|y6Q*|$3xZZ&6 zf{Nqs(9fG b5^Dan9Oew3p(AvNiYa74kQd k%u21__VSl%k1%>RiTB;omrM0 #~ zUGB Ma6l;9*nlwa0r49uUL(1l z7ibJ|BM&fA>Xl!Bcqh7il}~Es!)IL>$DfO7+;6L!3K6Ro&)ns{*9o|s+RPwRLuD$s zAN?zUjlL^xOoXBJfcsjFBdb|T<4A*uYr+8ZNx9Ml(%{|BtvPS#m({P7`yAWSu4SbA zd0WyHXh-iZpac+|^M3A S^^QA@}LtfTGuaSGRzSvJ;z+1Dw;M@0^knpip7#_myir zV_Z-WGzPz3R g26;i-Ket0x$p{nNDHZq9*wdQzPAxpmtxCn35bO6qX+{c9`@ zSq~~@L$|=ov<$%@_oN F)!tpTM&br7j?{Ecn`xRt(N EHjPe%kC7CkBhy6<&Gtd1;C=fA`HRp{C^E`6^ wcyVN= S1P^~LSQ@H2DwWEJcmD(3qHSjY literal 0 HcmV?d00001 diff --git a/app/appfront/theme/base/front/assets/fancybox/helpers/fancybox_buttons.png b/app/appfront/theme/base/front/assets/fancybox/helpers/fancybox_buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..07872072704114b91681e2e6f9697ce1521b64d2 GIT binary patch literal 1080 zcmeAS@N?(olHy`uVBq!ia0vp^Q6S903?%u>HW~n_y#YQUu0R?WSg~RSP%1Go5lD7* zbwQLpe*757ICA6&kW5WYZD?o!GK`Ilf#ib+545$lfs7|lo|Kf7golSGBqXd|yY}6? zcgK$(2by;H@Zldne!PGGe#3?hK*r6RH}~(~f9%+?@87@w1cMhZUi|v?>-O#24<9~! z_3G8{-@iY6_yAP-?b|mX`_G?0|Ns97D*W>0%coDDfKr0iiH$(}%u0g%f*BZ@S=qVy z1VzPV E?Tl=<;G1rjvPIE`Ra{3j~;*c^fm05 z&}0S%rZ1i@jv*CsZ>PnU&vFoGYh)GcNLbUk(XcbqE{E69EG*srz@Pu~uR3~FiyV{r zKBIe^jd`)*o5yoLKHYF_zn{1F51Du38}jGBJ=VP0ecMa>bF+9K`W*ijXIeka_uU8A z*POd = z37@}bnmsYU%ylPY9@}5u*!t|)yNM@Xh;kTr{CTM%UpgJrq;^z1sCv#Ff{JcXH0QycQ=j-SpqK)3sqC&x%d{>uv#p4L4W% zmLHbjTwSCP^ID(pX0NGG_)`a^m0!6nD|Dt#Dvad0vf#zR 8xqRnG{y^pfbH6Kc3;s;HW4p`heoW(jKH<7AtsEly z$M&AE{dQl2(Z%x9#dt|gSIbWy<4Xjtobc#5EmRoE7k>Wa#EFw7ELWat{GexP^oT7` zWJjo_z_Z6E{wwPO!J9zw9U;?iE rx;1Arv+D^&N20C4AEY>{Ek`B=i66zn9m4$^{AUqIL)kd`}_|Y zirXZ4+!kL{DD1t`cieXN&YnLTl;^yVdNTEd730M4<~70>Dwl5dOP&;N_1dH)?&X@x qGoDO6XT>`g#8(4K<@tG^_7CJ-u|B8Hp&OWk7(8A5T-G@yGywqna}dM; literal 0 HcmV?d00001 diff --git a/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-buttons.css b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-buttons.css new file mode 100644 index 000000000..302d6d5be --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-buttons.css @@ -0,0 +1,97 @@ +#fancybox-buttons { + position: fixed; + left: 0; + width: 100%; + z-index: 8050; +} + +#fancybox-buttons.top { + top: 10px; +} + +#fancybox-buttons.bottom { + bottom: 10px; +} + +#fancybox-buttons ul { + display: block; + width: 166px; + height: 30px; + margin: 0 auto; + padding: 0; + list-style: none; + border: 1px solid #111; + border-radius: 3px; + -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); + -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); + box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); + background: rgb(50,50,50); + background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51))); + background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + background: linear-gradient(to bottom, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 ); +} + +#fancybox-buttons ul li { + float: left; + margin: 0; + padding: 0; +} + +#fancybox-buttons a { + display: block; + width: 30px; + height: 30px; + text-indent: -9999px; + background-color: transparent; + background-image: url('fancybox_buttons.png'); + background-repeat: no-repeat; + outline: none; + opacity: 0.8; +} + +#fancybox-buttons a:hover { + opacity: 1; +} + +#fancybox-buttons a.btnPrev { + background-position: 5px 0; +} + +#fancybox-buttons a.btnNext { + background-position: -33px 0; + border-right: 1px solid #3e3e3e; +} + +#fancybox-buttons a.btnPlay { + background-position: 0 -30px; +} + +#fancybox-buttons a.btnPlayOn { + background-position: -30px -30px; +} + +#fancybox-buttons a.btnToggle { + background-position: 3px -60px; + border-left: 1px solid #111; + border-right: 1px solid #3e3e3e; + width: 35px +} + +#fancybox-buttons a.btnToggleOn { + background-position: -27px -60px; +} + +#fancybox-buttons a.btnClose { + border-left: 1px solid #111; + width: 35px; + background-position: -56px 0px; +} + +#fancybox-buttons a.btnDisabled { + opacity : 0.4; + cursor: default; +} diff --git a/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-buttons.js b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-buttons.js new file mode 100644 index 000000000..352bb5f0d --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-buttons.js @@ -0,0 +1,122 @@ + /*! + * Buttons helper for fancyBox + * version: 1.0.5 (Mon, 15 Oct 2012) + * @requires fancyBox v2.0 or later + * + * Usage: + * $(".fancybox").fancybox({ + * helpers : { + * buttons: { + * position : 'top' + * } + * } + * }); + * + */ +;(function ($) { + //Shortcut for fancyBox object + var F = $.fancybox; + + //Add helper object + F.helpers.buttons = { + defaults : { + skipSingle : false, // disables if gallery contains single image + position : 'top', // 'top' or 'bottom' + tpl : ' ' + }, + + list : null, + buttons: null, + + beforeLoad: function (opts, obj) { + //Remove self if gallery do not have at least two items + + if (opts.skipSingle && obj.group.length < 2) { + obj.helpers.buttons = false; + obj.closeBtn = true; + + return; + } + + //Increase top margin to give space for buttons + obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30; + }, + + onPlayStart: function () { + if (this.buttons) { + this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn'); + } + }, + + onPlayEnd: function () { + if (this.buttons) { + this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn'); + } + }, + + afterShow: function (opts, obj) { + var buttons = this.buttons; + + if (!buttons) { + this.list = $(opts.tpl).addClass(opts.position).appendTo('body'); + + buttons = { + prev : this.list.find('.btnPrev').click( F.prev ), + next : this.list.find('.btnNext').click( F.next ), + play : this.list.find('.btnPlay').click( F.play ), + toggle : this.list.find('.btnToggle').click( F.toggle ), + close : this.list.find('.btnClose').click( F.close ) + } + } + + //Prev + if (obj.index > 0 || obj.loop) { + buttons.prev.removeClass('btnDisabled'); + } else { + buttons.prev.addClass('btnDisabled'); + } + + //Next / Play + if (obj.loop || obj.index < obj.group.length - 1) { + buttons.next.removeClass('btnDisabled'); + buttons.play.removeClass('btnDisabled'); + + } else { + buttons.next.addClass('btnDisabled'); + buttons.play.addClass('btnDisabled'); + } + + this.buttons = buttons; + + this.onUpdate(opts, obj); + }, + + onUpdate: function (opts, obj) { + var toggle; + + if (!this.buttons) { + return; + } + + toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn'); + + //Size toggle button + if (obj.canShrink) { + toggle.addClass('btnToggleOn'); + + } else if (!obj.canExpand) { + toggle.addClass('btnDisabled'); + } + }, + + beforeClose: function () { + if (this.list) { + this.list.remove(); + } + + this.list = null; + this.buttons = null; + } + }; + +}(jQuery)); diff --git a/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-media.js b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-media.js new file mode 100644 index 000000000..99e62127a --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-media.js @@ -0,0 +1,201 @@ +/*! + * Media helper for fancyBox + * version: 1.0.6 (Fri, 14 Jun 2013) + * @requires fancyBox v2.0 or later + * + * Usage: + * $(".fancybox").fancybox({ + * helpers : { + * media: true + * } + * }); + * + * Set custom URL parameters: + * $(".fancybox").fancybox({ + * helpers : { + * media: { + * youtube : { + * params : { + * autoplay : 0 + * } + * } + * } + * } + * }); + * + * Or: + * $(".fancybox").fancybox({, + * helpers : { + * media: true + * }, + * youtube : { + * autoplay: 0 + * } + * }); + * + * Supports: + * + * Youtube + * http://www.youtube.com/watch?v=opj24KnzrWo + * http://www.youtube.com/embed/opj24KnzrWo + * http://youtu.be/opj24KnzrWo + * http://www.youtube-nocookie.com/embed/opj24KnzrWo + * Vimeo + * http://vimeo.com/40648169 + * http://vimeo.com/channels/staffpicks/38843628 + * http://vimeo.com/groups/surrealism/videos/36516384 + * http://player.vimeo.com/video/45074303 + * Metacafe + * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/ + * http://www.metacafe.com/watch/7635964/ + * Dailymotion + * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people + * Twitvid + * http://twitvid.com/QY7MD + * Twitpic + * http://twitpic.com/7p93st + * Instagram + * http://instagr.am/p/IejkuUGxQn/ + * http://instagram.com/p/IejkuUGxQn/ + * Google maps + * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17 + * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16 + * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56 + */ +;(function ($) { + "use strict"; + + //Shortcut for fancyBox object + var F = $.fancybox, + format = function( url, rez, params ) { + params = params || ''; + + if ( $.type( params ) === "object" ) { + params = $.param(params, true); + } + + $.each(rez, function(key, value) { + url = url.replace( '$' + key, value || '' ); + }); + + if (params.length) { + url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params; + } + + return url; + }; + + //Add helper object + F.helpers.media = { + defaults : { + youtube : { + matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i, + params : { + autoplay : 1, + autohide : 1, + fs : 1, + rel : 0, + hd : 1, + wmode : 'opaque', + enablejsapi : 1, + ps: 'docs', + controls: 1 + }, + type : 'iframe', + url : '//www.youtube.com/embed/$3' + }, + vimeo : { + matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/, + params : { + autoplay : 1, + hd : 1, + show_title : 1, + show_byline : 1, + show_portrait : 0, + fullscreen : 1 + }, + type : 'iframe', + url : '//player.vimeo.com/video/$1' + }, + metacafe : { + matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/, + params : { + autoPlay : 'yes' + }, + type : 'swf', + url : function( rez, params, obj ) { + obj.swf.flashVars = 'playerVars=' + $.param( params, true ); + + return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf'; + } + }, + dailymotion : { + matcher : /dailymotion.com\/video\/(.*)\/?(.*)/, + params : { + additionalInfos : 0, + autoStart : 1 + }, + type : 'swf', + url : '//www.dailymotion.com/swf/video/$1' + }, + twitvid : { + matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i, + params : { + autoplay : 0 + }, + type : 'iframe', + url : '//www.twitvid.com/embed.php?guid=$1' + }, + twitpic : { + matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i, + type : 'image', + url : '//twitpic.com/show/full/$1/' + }, + instagram : { + matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i, + type : 'image', + url : '//$1/p/$2/media/?size=l' + }, + google_maps : { + matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i, + type : 'iframe', + url : function( rez ) { + return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed'); + } + } + }, + + beforeLoad : function(opts, obj) { + var url = obj.href || '', + type = false, + what, + item, + rez, + params; + + for (what in opts) { + if (opts.hasOwnProperty(what)) { + item = opts[ what ]; + rez = url.match( item.matcher ); + + if (rez) { + type = item.type; + params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null)); + + url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params ); + + break; + } + } + } + + if (type) { + obj.href = url; + obj.type = type; + + obj.autoHeight = false; + } + } + }; + +}(jQuery)); diff --git a/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-thumbs.css b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-thumbs.css new file mode 100644 index 000000000..63d294368 --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-thumbs.css @@ -0,0 +1,55 @@ +#fancybox-thumbs { + position: fixed; + left: 0; + width: 100%; + overflow: hidden; + z-index: 8050; +} + +#fancybox-thumbs.bottom { + bottom: 2px; +} + +#fancybox-thumbs.top { + top: 2px; +} + +#fancybox-thumbs ul { + position: relative; + list-style: none; + margin: 0; + padding: 0; +} + +#fancybox-thumbs ul li { + float: left; + padding: 1px; + opacity: 0.5; +} + +#fancybox-thumbs ul li.active { + opacity: 0.75; + padding: 0; + border: 1px solid #fff; +} + +#fancybox-thumbs ul li:hover { + opacity: 1; +} + +#fancybox-thumbs ul li a { + display: block; + position: relative; + overflow: hidden; + border: 1px solid #222; + background: #111; + outline: none; +} + +#fancybox-thumbs ul li img { + display: block; + position: relative; + border: 0; + padding: 0; + max-width: none; +} \ No newline at end of file diff --git a/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-thumbs.js b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-thumbs.js new file mode 100644 index 000000000..58c971943 --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/helpers/jquery.fancybox-thumbs.js @@ -0,0 +1,165 @@ + /*! + * Thumbnail helper for fancyBox + * version: 1.0.7 (Mon, 01 Oct 2012) + * @requires fancyBox v2.0 or later + * + * Usage: + * $(".fancybox").fancybox({ + * helpers : { + * thumbs: { + * width : 50, + * height : 50 + * } + * } + * }); + * + */ +;(function ($) { + //Shortcut for fancyBox object + var F = $.fancybox; + + //Add helper object + F.helpers.thumbs = { + defaults : { + width : 50, // thumbnail width + height : 50, // thumbnail height + position : 'bottom', // 'top' or 'bottom' + source : function ( item ) { // function to obtain the URL of the thumbnail image + var href; + + if (item.element) { + href = $(item.element).find('img').attr('src'); + } + + if (!href && item.type === 'image' && item.href) { + href = item.href; + } + + return href; + } + }, + + wrap : null, + list : null, + width : 0, + + init: function (opts, obj) { + var that = this, + list, + thumbWidth = opts.width, + thumbHeight = opts.height, + thumbSource = opts.source; + + //Build list structure + list = ''; + + for (var n = 0; n < obj.group.length; n++) { + list += ''; + } + + this.wrap = $('').addClass(opts.position).appendTo('body'); + this.list = $(' ' + list + '
').appendTo(this.wrap); + + //Load each thumbnail + $.each(obj.group, function (i) { + var el = obj.group[ i ], + href = thumbSource( el ); + + if (!href) { + return; + } + + $("").load(function () { + var width = this.width, + height = this.height, + widthRatio, heightRatio, parent; + + if (!that.list || !width || !height) { + return; + } + + //Calculate thumbnail width/height and center it + widthRatio = width / thumbWidth; + heightRatio = height / thumbHeight; + + parent = that.list.children().eq(i).find('a'); + + if (widthRatio >= 1 && heightRatio >= 1) { + if (widthRatio > heightRatio) { + width = Math.floor(width / heightRatio); + height = thumbHeight; + + } else { + width = thumbWidth; + height = Math.floor(height / widthRatio); + } + } + + $(this).css({ + width : width, + height : height, + top : Math.floor(thumbHeight / 2 - height / 2), + left : Math.floor(thumbWidth / 2 - width / 2) + }); + + parent.width(thumbWidth).height(thumbHeight); + + $(this).hide().appendTo(parent).fadeIn(300); + + }) + .attr('src', href) + .attr('title', el.title); + }); + + //Set initial width + this.width = this.list.children().eq(0).outerWidth(true); + + this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))); + }, + + beforeLoad: function (opts, obj) { + //Remove self if gallery do not have at least two items + if (obj.group.length < 2) { + obj.helpers.thumbs = false; + + return; + } + + //Increase bottom margin to give space for thumbs + obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15); + }, + + afterShow: function (opts, obj) { + //Check if exists and create or update list + if (this.list) { + this.onUpdate(opts, obj); + + } else { + this.init(opts, obj); + } + + //Set active element + this.list.children().removeClass('active').eq(obj.index).addClass('active'); + }, + + //Center list + onUpdate: function (opts, obj) { + if (this.list) { + this.list.stop(true).animate({ + 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)) + }, 150); + } + }, + + beforeClose: function () { + if (this.wrap) { + this.wrap.remove(); + } + + this.wrap = null; + this.list = null; + this.width = 0; + } + } + +}(jQuery)); \ No newline at end of file diff --git a/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.css b/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.css new file mode 100644 index 000000000..fb2c6dd28 --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.css @@ -0,0 +1,275 @@ +/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ +.fancybox-wrap, +.fancybox-skin, +.fancybox-outer, +.fancybox-inner, +.fancybox-image, +.fancybox-wrap iframe, +.fancybox-wrap object, +.fancybox-nav, +.fancybox-nav span, +.fancybox-tmp +{ + padding: 0; + margin: 0; + border: 0; + outline: none; + vertical-align: top; +} + +.fancybox-wrap { + position: absolute; + top: 0; + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + z-index: 8020; +} + +.fancybox-skin { + position: relative; + background: #f9f9f9; + color: #444; + text-shadow: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.fancybox-opened { + z-index: 8030; +} + +.fancybox-opened .fancybox-skin { + -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); +} + +.fancybox-outer, .fancybox-inner { + position: relative; +} + +.fancybox-inner { + overflow: hidden; +} + +.fancybox-type-iframe .fancybox-inner { + -webkit-overflow-scrolling: touch; +} + +.fancybox-error { + color: #444; + font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; + margin: 0; + padding: 15px; + white-space: nowrap; +} + +.fancybox-image, .fancybox-iframe { + display: block; + width: 100%; + height: 100%; +} + +.fancybox-image { + max-width: 100%; + max-height: 100%; +} + +#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { + background-image: url(fancybox_sprite.png); +} + +#fancybox-loading { + position: fixed; + top: 50%; + left: 50%; + margin-top: -22px; + margin-left: -22px; + background-position: 0 -108px; + opacity: 0.8; + cursor: pointer; + z-index: 8060; +} + +#fancybox-loading div { + width: 44px; + height: 44px; + background: url(fancybox_loading.gif) center center no-repeat; +} + +.fancybox-close { + position: absolute; + top: -18px; + right: -18px; + width: 36px; + height: 36px; + cursor: pointer; + z-index: 8040; +} + +.fancybox-nav { + position: absolute; + top: 0; + width: 40%; + height: 100%; + cursor: pointer; + text-decoration: none; + background: transparent url(blank.gif); /* helps IE */ + -webkit-tap-highlight-color: rgba(0,0,0,0); + z-index: 8040; +} + +.fancybox-prev { + left: 0; +} + +.fancybox-next { + right: 0; +} + +.fancybox-nav span { + position: absolute; + top: 50%; + width: 36px; + height: 34px; + margin-top: -18px; + cursor: pointer; + z-index: 8040; + visibility: hidden; +} + +.fancybox-prev span { + left: 10px; + background-position: 0 -36px; +} + +.fancybox-next span { + right: 10px; + background-position: 0 -72px; +} + +.fancybox-nav:hover span { + visibility: visible; +} + +.fancybox-tmp { + position: absolute; + top: -99999px; + left: -99999px; + max-width: 99999px; + max-height: 99999px; + overflow: visible !important; +} + +/* Overlay helper */ + +.fancybox-lock { + overflow: visible !important; + width: auto; +} + +.fancybox-lock body { + overflow: hidden !important; +} + +.fancybox-lock-test { + overflow-y: hidden !important; +} + +.fancybox-overlay { + position: absolute; + top: 0; + left: 0; + overflow: hidden; + display: none; + z-index: 8010; + background: url(fancybox_overlay.png); +} + +.fancybox-overlay-fixed { + position: fixed; + bottom: 0; + right: 0; +} + +.fancybox-lock .fancybox-overlay { + overflow: auto; + overflow-y: scroll; +} + +/* Title helper */ + +.fancybox-title { + visibility: hidden; + font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; + position: relative; + text-shadow: none; + z-index: 8050; +} + +.fancybox-opened .fancybox-title { + visibility: visible; +} + +.fancybox-title-float-wrap { + position: absolute; + bottom: 0; + right: 50%; + margin-bottom: -35px; + z-index: 8050; + text-align: center; +} + +.fancybox-title-float-wrap .child { + display: inline-block; + margin-right: -100%; + padding: 2px 20px; + background: transparent; /* Fallback for web browsers that doesn't support RGBa */ + background: rgba(0, 0, 0, 0.8); + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; + text-shadow: 0 1px 2px #222; + color: #FFF; + font-weight: bold; + line-height: 24px; + white-space: nowrap; +} + +.fancybox-title-outside-wrap { + position: relative; + margin-top: 10px; + color: #fff; +} + +.fancybox-title-inside-wrap { + padding-top: 10px; +} + +.fancybox-title-over-wrap { + position: absolute; + bottom: 0; + left: 0; + color: #fff; + padding: 10px; + background: #000; + background: rgba(0, 0, 0, .8); +} + +/*Retina graphics!*/ +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), + only screen and (min--moz-device-pixel-ratio: 1.5), + only screen and (min-device-pixel-ratio: 1.5){ + + #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { + background-image: url(fancybox_sprite@2x.png); + background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/ + } + + #fancybox-loading div { + background-image: url(fancybox_loading@2x.gif); + background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/ + } +} \ No newline at end of file diff --git a/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.js b/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.js new file mode 100644 index 000000000..d126de495 --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.js @@ -0,0 +1,2018 @@ +/*! + * fancyBox - jQuery Plugin + * version: 2.1.5 (Fri, 14 Jun 2013) + * requires jQuery v1.6 or later + * + * Examples at http://fancyapps.com/fancybox/ + * License: www.fancyapps.com/fancybox/#license + * + * Copyright 2012 Janis Skarnelis - janis@fancyapps.com + * + */ + +;(function (window, document, $, undefined) { + "use strict"; + + var H = $("html"), + W = $(window), + D = $(document), + F = $.fancybox = function () { + F.open.apply( this, arguments ); + }, + IE = navigator.userAgent.match(/msie/i), + didUpdate = null, + isTouch = document.createTouch !== undefined, + + isQuery = function(obj) { + return obj && obj.hasOwnProperty && obj instanceof $; + }, + isString = function(str) { + return str && $.type(str) === "string"; + }, + isPercentage = function(str) { + return isString(str) && str.indexOf('%') > 0; + }, + isScrollable = function(el) { + return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); + }, + getScalar = function(orig, dim) { + var value = parseInt(orig, 10) || 0; + + if (dim && isPercentage(orig)) { + value = F.getViewport()[ dim ] / 100 * value; + } + + return Math.ceil(value); + }, + getValue = function(value, dim) { + return getScalar(value, dim) + 'px'; + }; + + $.extend(F, { + // The current version of fancyBox + version: '2.1.5', + + defaults: { + padding : 15, + margin : 20, + + width : 800, + height : 600, + minWidth : 100, + minHeight : 100, + maxWidth : 9999, + maxHeight : 9999, + pixelRatio: 1, // Set to 2 for retina display support + + autoSize : true, + autoHeight : false, + autoWidth : false, + + autoResize : true, + autoCenter : !isTouch, + fitToView : true, + aspectRatio : false, + topRatio : 0.5, + leftRatio : 0.5, + + scrolling : 'auto', // 'auto', 'yes' or 'no' + wrapCSS : '', + + arrows : true, + closeBtn : true, + closeClick : false, + nextClick : false, + mouseWheel : true, + autoPlay : false, + playSpeed : 3000, + preload : 3, + modal : false, + loop : true, + + ajax : { + dataType : 'html', + headers : { 'X-fancyBox': true } + }, + iframe : { + scrolling : 'auto', + preload : true + }, + swf : { + wmode: 'transparent', + allowfullscreen : 'true', + allowscriptaccess : 'always' + }, + + keys : { + next : { + 13 : 'left', // enter + 34 : 'up', // page down + 39 : 'left', // right arrow + 40 : 'up' // down arrow + }, + prev : { + 8 : 'right', // backspace + 33 : 'down', // page up + 37 : 'right', // left arrow + 38 : 'down' // up arrow + }, + close : [27], // escape key + play : [32], // space - start/stop slideshow + toggle : [70] // letter "f" - toggle fullscreen + }, + + direction : { + next : 'left', + prev : 'right' + }, + + scrollOutside : true, + + // Override some properties + index : 0, + type : null, + href : null, + content : null, + title : null, + + // HTML templates + tpl: { + wrap : '', + image : '', + iframe : '', + error : 'The requested content cannot be loaded.
', + closeBtn : '', + next : '', + prev : '', + loading : '
Please try again later.' + }, + + // Properties for each animation type + // Opening fancyBox + openEffect : 'fade', // 'elastic', 'fade' or 'none' + openSpeed : 250, + openEasing : 'swing', + openOpacity : true, + openMethod : 'zoomIn', + + // Closing fancyBox + closeEffect : 'fade', // 'elastic', 'fade' or 'none' + closeSpeed : 250, + closeEasing : 'swing', + closeOpacity : true, + closeMethod : 'zoomOut', + + // Changing next gallery item + nextEffect : 'elastic', // 'elastic', 'fade' or 'none' + nextSpeed : 250, + nextEasing : 'swing', + nextMethod : 'changeIn', + + // Changing previous gallery item + prevEffect : 'elastic', // 'elastic', 'fade' or 'none' + prevSpeed : 250, + prevEasing : 'swing', + prevMethod : 'changeOut', + + // Enable default helpers + helpers : { + overlay : true, + title : true + }, + + // Callbacks + onCancel : $.noop, // If canceling + beforeLoad : $.noop, // Before loading + afterLoad : $.noop, // After loading + beforeShow : $.noop, // Before changing in current item + afterShow : $.noop, // After opening + beforeChange : $.noop, // Before changing gallery item + beforeClose : $.noop, // Before closing + afterClose : $.noop // After closing + }, + + //Current state + group : {}, // Selected group + opts : {}, // Group options + previous : null, // Previous element + coming : null, // Element being loaded + current : null, // Currently loaded element + isActive : false, // Is activated + isOpen : false, // Is currently open + isOpened : false, // Have been fully opened at least once + + wrap : null, + skin : null, + outer : null, + inner : null, + + player : { + timer : null, + isActive : false + }, + + // Loaders + ajaxLoad : null, + imgPreload : null, + + // Some collections + transitions : {}, + helpers : {}, + + /* + * Static methods + */ + + open: function (group, opts) { + if (!group) { + return; + } + + if (!$.isPlainObject(opts)) { + opts = {}; + } + + // Close if already active + if (false === F.close(true)) { + return; + } + + // Normalize group + if (!$.isArray(group)) { + group = isQuery(group) ? $(group).get() : [group]; + } + + // Recheck if the type of each element is `object` and set content type (image, ajax, etc) + $.each(group, function(i, element) { + var obj = {}, + href, + title, + content, + type, + rez, + hrefParts, + selector; + + if ($.type(element) === "object") { + // Check if is DOM element + if (element.nodeType) { + element = $(element); + } + + if (isQuery(element)) { + obj = { + href : element.data('fancybox-href') || element.attr('href'), + title : $('').text( element.data('fancybox-title') || element.attr('title') || '' ).html(), + isDom : true, + element : element + }; + + if ($.metadata) { + $.extend(true, obj, element.metadata()); + } + + } else { + obj = element; + } + } + + href = opts.href || obj.href || (isString(element) ? element : null); + title = opts.title !== undefined ? opts.title : obj.title || ''; + + content = opts.content || obj.content; + type = content ? 'html' : (opts.type || obj.type); + + if (!type && obj.isDom) { + type = element.data('fancybox-type'); + + if (!type) { + rez = element.prop('class').match(/fancybox\.(\w+)/); + type = rez ? rez[1] : null; + } + } + + if (isString(href)) { + // Try to guess the content type + if (!type) { + if (F.isImage(href)) { + type = 'image'; + + } else if (F.isSWF(href)) { + type = 'swf'; + + } else if (href.charAt(0) === '#') { + type = 'inline'; + + } else if (isString(element)) { + type = 'html'; + content = element; + } + } + + // Split url into two pieces with source url and content selector, e.g, + // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" + if (type === 'ajax') { + hrefParts = href.split(/\s+/, 2); + href = hrefParts.shift(); + selector = hrefParts.shift(); + } + } + + if (!content) { + if (type === 'inline') { + if (href) { + content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 + + } else if (obj.isDom) { + content = element; + } + + } else if (type === 'html') { + content = href; + + } else if (!type && !href && obj.isDom) { + type = 'inline'; + content = element; + } + } + + $.extend(obj, { + href : href, + type : type, + content : content, + title : title, + selector : selector + }); + + group[ i ] = obj; + }); + + // Extend the defaults + F.opts = $.extend(true, {}, F.defaults, opts); + + // All options are merged recursive except keys + if (opts.keys !== undefined) { + F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; + } + + F.group = group; + + return F._start(F.opts.index); + }, + + // Cancel image loading or abort ajax request + cancel: function () { + var coming = F.coming; + + if (coming && false === F.trigger('onCancel')) { + return; + } + + F.hideLoading(); + + if (!coming) { + return; + } + + if (F.ajaxLoad) { + F.ajaxLoad.abort(); + } + + F.ajaxLoad = null; + + if (F.imgPreload) { + F.imgPreload.onload = F.imgPreload.onerror = null; + } + + if (coming.wrap) { + coming.wrap.stop(true, true).trigger('onReset').remove(); + } + + F.coming = null; + + // If the first item has been canceled, then clear everything + if (!F.current) { + F._afterZoomOut( coming ); + } + }, + + // Start closing animation if is open; remove immediately if opening/closing + close: function (event) { + F.cancel(); + + if (false === F.trigger('beforeClose')) { + return; + } + + F.unbindEvents(); + + if (!F.isActive) { + return; + } + + if (!F.isOpen || event === true) { + $('.fancybox-wrap').stop(true).trigger('onReset').remove(); + + F._afterZoomOut(); + + } else { + F.isOpen = F.isOpened = false; + F.isClosing = true; + + $('.fancybox-item, .fancybox-nav').remove(); + + F.wrap.stop(true, true).removeClass('fancybox-opened'); + + F.transitions[ F.current.closeMethod ](); + } + }, + + // Manage slideshow: + // $.fancybox.play(); - toggle slideshow + // $.fancybox.play( true ); - start + // $.fancybox.play( false ); - stop + play: function ( action ) { + var clear = function () { + clearTimeout(F.player.timer); + }, + set = function () { + clear(); + + if (F.current && F.player.isActive) { + F.player.timer = setTimeout(F.next, F.current.playSpeed); + } + }, + stop = function () { + clear(); + + D.unbind('.player'); + + F.player.isActive = false; + + F.trigger('onPlayEnd'); + }, + start = function () { + if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { + F.player.isActive = true; + + D.bind({ + 'onCancel.player beforeClose.player' : stop, + 'onUpdate.player' : set, + 'beforeLoad.player' : clear + }); + + set(); + + F.trigger('onPlayStart'); + } + }; + + if (action === true || (!F.player.isActive && action !== false)) { + start(); + } else { + stop(); + } + }, + + // Navigate to next gallery item + next: function ( direction ) { + var current = F.current; + + if (current) { + if (!isString(direction)) { + direction = current.direction.next; + } + + F.jumpto(current.index + 1, direction, 'next'); + } + }, + + // Navigate to previous gallery item + prev: function ( direction ) { + var current = F.current; + + if (current) { + if (!isString(direction)) { + direction = current.direction.prev; + } + + F.jumpto(current.index - 1, direction, 'prev'); + } + }, + + // Navigate to gallery item by index + jumpto: function ( index, direction, router ) { + var current = F.current; + + if (!current) { + return; + } + + index = getScalar(index); + + F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; + F.router = router || 'jumpto'; + + if (current.loop) { + if (index < 0) { + index = current.group.length + (index % current.group.length); + } + + index = index % current.group.length; + } + + if (current.group[ index ] !== undefined) { + F.cancel(); + + F._start(index); + } + }, + + // Center inside viewport and toggle position type to fixed or absolute if needed + reposition: function (e, onlyAbsolute) { + var current = F.current, + wrap = current ? current.wrap : null, + pos; + + if (wrap) { + pos = F._getPosition(onlyAbsolute); + + if (e && e.type === 'scroll') { + delete pos.position; + + wrap.stop(true, true).animate(pos, 200); + + } else { + wrap.css(pos); + + current.pos = $.extend({}, current.dim, pos); + } + } + }, + + update: function (e) { + var type = (e && e.originalEvent && e.originalEvent.type), + anyway = !type || type === 'orientationchange'; + + if (anyway) { + clearTimeout(didUpdate); + + didUpdate = null; + } + + if (!F.isOpen || didUpdate) { + return; + } + + didUpdate = setTimeout(function() { + var current = F.current; + + if (!current || F.isClosing) { + return; + } + + F.wrap.removeClass('fancybox-tmp'); + + if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { + F._setDimension(); + } + + if (!(type === 'scroll' && current.canShrink)) { + F.reposition(e); + } + + F.trigger('onUpdate'); + + didUpdate = null; + + }, (anyway && !isTouch ? 0 : 300)); + }, + + // Shrink content to fit inside viewport or restore if resized + toggle: function ( action ) { + if (F.isOpen) { + F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; + + // Help browser to restore document dimensions + if (isTouch) { + F.wrap.removeAttr('style').addClass('fancybox-tmp'); + + F.trigger('onUpdate'); + } + + F.update(); + } + }, + + hideLoading: function () { + D.unbind('.loading'); + + $('#fancybox-loading').remove(); + }, + + showLoading: function () { + var el, viewport; + + F.hideLoading(); + + el = $(F.opts.tpl.loading).click(F.cancel).appendTo('body'); + + // If user will press the escape-button, the request will be canceled + D.bind('keydown.loading', function(e) { + if ((e.which || e.keyCode) === 27) { + e.preventDefault(); + + F.cancel(); + } + }); + + if (!F.defaults.fixed) { + viewport = F.getViewport(); + + el.css({ + position : 'absolute', + top : (viewport.h * 0.5) + viewport.y, + left : (viewport.w * 0.5) + viewport.x + }); + } + + F.trigger('onLoading'); + }, + + getViewport: function () { + var locked = (F.current && F.current.locked) || false, + rez = { + x: W.scrollLeft(), + y: W.scrollTop() + }; + + if (locked && locked.length) { + rez.w = locked[0].clientWidth; + rez.h = locked[0].clientHeight; + + } else { + // See http://bugs.jquery.com/ticket/6724 + rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); + rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); + } + + return rez; + }, + + // Unbind the keyboard / clicking actions + unbindEvents: function () { + if (F.wrap && isQuery(F.wrap)) { + F.wrap.unbind('.fb'); + } + + D.unbind('.fb'); + W.unbind('.fb'); + }, + + bindEvents: function () { + var current = F.current, + keys; + + if (!current) { + return; + } + + // Changing document height on iOS devices triggers a 'resize' event, + // that can change document height... repeating infinitely + W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); + + keys = current.keys; + + if (keys) { + D.bind('keydown.fb', function (e) { + var code = e.which || e.keyCode, + target = e.target || e.srcElement; + + // Skip esc key if loading, because showLoading will cancel preloading + if (code === 27 && F.coming) { + return false; + } + + // Ignore key combinations and key events within form elements + if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { + $.each(keys, function(i, val) { + if (current.group.length > 1 && val[ code ] !== undefined) { + F[ i ]( val[ code ] ); + + e.preventDefault(); + return false; + } + + if ($.inArray(code, val) > -1) { + F[ i ] (); + + e.preventDefault(); + return false; + } + }); + } + }); + } + + if ($.fn.mousewheel && current.mouseWheel) { + F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { + var target = e.target || null, + parent = $(target), + canScroll = false; + + while (parent.length) { + if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { + break; + } + + canScroll = isScrollable( parent[0] ); + parent = $(parent).parent(); + } + + if (delta !== 0 && !canScroll) { + if (F.group.length > 1 && !current.canShrink) { + if (deltaY > 0 || deltaX > 0) { + F.prev( deltaY > 0 ? 'down' : 'left' ); + + } else if (deltaY < 0 || deltaX < 0) { + F.next( deltaY < 0 ? 'up' : 'right' ); + } + + e.preventDefault(); + } + } + }); + } + }, + + trigger: function (event, o) { + var ret, obj = o || F.coming || F.current; + + if (obj) { + if ($.isFunction( obj[event] )) { + ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); + } + + if (ret === false) { + return false; + } + + if (obj.helpers) { + $.each(obj.helpers, function (helper, opts) { + if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { + F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj); + } + }); + } + } + + D.trigger(event); + }, + + isImage: function (str) { + return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); + }, + + isSWF: function (str) { + return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); + }, + + _start: function (index) { + var coming = {}, + obj, + href, + type, + margin, + padding; + + index = getScalar( index ); + obj = F.group[ index ] || null; + + if (!obj) { + return false; + } + + coming = $.extend(true, {}, F.opts, obj); + + // Convert margin and padding properties to array - top, right, bottom, left + margin = coming.margin; + padding = coming.padding; + + if ($.type(margin) === 'number') { + coming.margin = [margin, margin, margin, margin]; + } + + if ($.type(padding) === 'number') { + coming.padding = [padding, padding, padding, padding]; + } + + // 'modal' propery is just a shortcut + if (coming.modal) { + $.extend(true, coming, { + closeBtn : false, + closeClick : false, + nextClick : false, + arrows : false, + mouseWheel : false, + keys : null, + helpers: { + overlay : { + closeClick : false + } + } + }); + } + + // 'autoSize' property is a shortcut, too + if (coming.autoSize) { + coming.autoWidth = coming.autoHeight = true; + } + + if (coming.width === 'auto') { + coming.autoWidth = true; + } + + if (coming.height === 'auto') { + coming.autoHeight = true; + } + + /* + * Add reference to the group, so it`s possible to access from callbacks, example: + * afterLoad : function() { + * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); + * } + */ + + coming.group = F.group; + coming.index = index; + + // Give a chance for callback or helpers to update coming item (type, title, etc) + F.coming = coming; + + if (false === F.trigger('beforeLoad')) { + F.coming = null; + + return; + } + + type = coming.type; + href = coming.href; + + if (!type) { + F.coming = null; + + //If we can not determine content type then drop silently or display next/prev item if looping through gallery + if (F.current && F.router && F.router !== 'jumpto') { + F.current.index = index; + + return F[ F.router ]( F.direction ); + } + + return false; + } + + F.isActive = true; + + if (type === 'image' || type === 'swf') { + coming.autoHeight = coming.autoWidth = false; + coming.scrolling = 'visible'; + } + + if (type === 'image') { + coming.aspectRatio = true; + } + + if (type === 'iframe' && isTouch) { + coming.scrolling = 'scroll'; + } + + // Build the neccessary markup + coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); + + $.extend(coming, { + skin : $('.fancybox-skin', coming.wrap), + outer : $('.fancybox-outer', coming.wrap), + inner : $('.fancybox-inner', coming.wrap) + }); + + $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { + coming.skin.css('padding' + v, getValue(coming.padding[ i ])); + }); + + F.trigger('onReady'); + + // Check before try to load; 'inline' and 'html' types need content, others - href + if (type === 'inline' || type === 'html') { + if (!coming.content || !coming.content.length) { + return F._error( 'content' ); + } + + } else if (!href) { + return F._error( 'href' ); + } + + if (type === 'image') { + F._loadImage(); + + } else if (type === 'ajax') { + F._loadAjax(); + + } else if (type === 'iframe') { + F._loadIframe(); + + } else { + F._afterLoad(); + } + }, + + _error: function ( type ) { + $.extend(F.coming, { + type : 'html', + autoWidth : true, + autoHeight : true, + minWidth : 0, + minHeight : 0, + scrolling : 'no', + hasError : type, + content : F.coming.tpl.error + }); + + F._afterLoad(); + }, + + _loadImage: function () { + // Reset preload image so it is later possible to check "complete" property + var img = F.imgPreload = new Image(); + + img.onload = function () { + this.onload = this.onerror = null; + + F.coming.width = this.width / F.opts.pixelRatio; + F.coming.height = this.height / F.opts.pixelRatio; + + F._afterLoad(); + }; + + img.onerror = function () { + this.onload = this.onerror = null; + + F._error( 'image' ); + }; + + img.src = F.coming.href; + + if (img.complete !== true) { + F.showLoading(); + } + }, + + _loadAjax: function () { + var coming = F.coming; + + F.showLoading(); + + F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { + url: coming.href, + error: function (jqXHR, textStatus) { + if (F.coming && textStatus !== 'abort') { + F._error( 'ajax', jqXHR ); + + } else { + F.hideLoading(); + } + }, + success: function (data, textStatus) { + if (textStatus === 'success') { + coming.content = data; + + F._afterLoad(); + } + } + })); + }, + + _loadIframe: function() { + var coming = F.coming, + iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) + .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) + .attr('src', coming.href); + + // This helps IE + $(coming.wrap).bind('onReset', function () { + try { + $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); + } catch (e) {} + }); + + if (coming.iframe.preload) { + F.showLoading(); + + iframe.one('load', function() { + $(this).data('ready', 1); + + // iOS will lose scrolling if we resize + if (!isTouch) { + $(this).bind('load.fb', F.update); + } + + // Without this trick: + // - iframe won't scroll on iOS devices + // - IE7 sometimes displays empty iframe + $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); + + F._afterLoad(); + }); + } + + coming.content = iframe.appendTo( coming.inner ); + + if (!coming.iframe.preload) { + F._afterLoad(); + } + }, + + _preloadImages: function() { + var group = F.group, + current = F.current, + len = group.length, + cnt = current.preload ? Math.min(current.preload, len - 1) : 0, + item, + i; + + for (i = 1; i <= cnt; i += 1) { + item = group[ (current.index + i ) % len ]; + + if (item.type === 'image' && item.href) { + new Image().src = item.href; + } + } + }, + + _afterLoad: function () { + var coming = F.coming, + previous = F.current, + placeholder = 'fancybox-placeholder', + current, + content, + type, + scrolling, + href, + embed; + + F.hideLoading(); + + if (!coming || F.isActive === false) { + return; + } + + if (false === F.trigger('afterLoad', coming, previous)) { + coming.wrap.stop(true).trigger('onReset').remove(); + + F.coming = null; + + return; + } + + if (previous) { + F.trigger('beforeChange', previous); + + previous.wrap.stop(true).removeClass('fancybox-opened') + .find('.fancybox-item, .fancybox-nav') + .remove(); + } + + F.unbindEvents(); + + current = coming; + content = coming.content; + type = coming.type; + scrolling = coming.scrolling; + + $.extend(F, { + wrap : current.wrap, + skin : current.skin, + outer : current.outer, + inner : current.inner, + current : current, + previous : previous + }); + + href = current.href; + + switch (type) { + case 'inline': + case 'ajax': + case 'html': + if (current.selector) { + content = $('').html(content).find(current.selector); + + } else if (isQuery(content)) { + if (!content.data(placeholder)) { + content.data(placeholder, $('').insertAfter( content ).hide() ); + } + + content = content.show().detach(); + + current.wrap.bind('onReset', function () { + if ($(this).find(content).length) { + content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); + } + }); + } + break; + + case 'image': + content = current.tpl.image.replace(/\{href\}/g, href); + break; + + case 'swf': + content = ''; + break; + } + + if (!(isQuery(content) && content.parent().is(current.inner))) { + current.inner.append( content ); + } + + // Give a chance for helpers or callbacks to update elements + F.trigger('beforeShow'); + + // Set scrolling before calculating dimensions + current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); + + // Set initial dimensions and start position + F._setDimension(); + + F.reposition(); + + F.isOpen = false; + F.coming = null; + + F.bindEvents(); + + if (!F.isOpened) { + $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); + + } else if (previous.prevMethod) { + F.transitions[ previous.prevMethod ](); + } + + F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); + + F._preloadImages(); + }, + + _setDimension: function () { + var viewport = F.getViewport(), + steps = 0, + canShrink = false, + canExpand = false, + wrap = F.wrap, + skin = F.skin, + inner = F.inner, + current = F.current, + width = current.width, + height = current.height, + minWidth = current.minWidth, + minHeight = current.minHeight, + maxWidth = current.maxWidth, + maxHeight = current.maxHeight, + scrolling = current.scrolling, + scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, + margin = current.margin, + wMargin = getScalar(margin[1] + margin[3]), + hMargin = getScalar(margin[0] + margin[2]), + wPadding, + hPadding, + wSpace, + hSpace, + origWidth, + origHeight, + origMaxWidth, + origMaxHeight, + ratio, + width_, + height_, + maxWidth_, + maxHeight_, + iframe, + body; + + // Reset dimensions so we could re-check actual size + wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); + + wPadding = getScalar(skin.outerWidth(true) - skin.width()); + hPadding = getScalar(skin.outerHeight(true) - skin.height()); + + // Any space between content and viewport (margin, padding, border, title) + wSpace = wMargin + wPadding; + hSpace = hMargin + hPadding; + + origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; + origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; + + if (current.type === 'iframe') { + iframe = current.content; + + if (current.autoHeight && iframe && iframe.data('ready') === 1) { + try { + if (iframe[0].contentWindow.document.location) { + inner.width( origWidth ).height(9999); + + body = iframe.contents().find('body'); + + if (scrollOut) { + body.css('overflow-x', 'hidden'); + } + + origHeight = body.outerHeight(true); + } + + } catch (e) {} + } + + } else if (current.autoWidth || current.autoHeight) { + inner.addClass( 'fancybox-tmp' ); + + // Set width or height in case we need to calculate only one dimension + if (!current.autoWidth) { + inner.width( origWidth ); + } + + if (!current.autoHeight) { + inner.height( origHeight ); + } + + if (current.autoWidth) { + origWidth = inner.width(); + } + + if (current.autoHeight) { + origHeight = inner.height(); + } + + inner.removeClass( 'fancybox-tmp' ); + } + + width = getScalar( origWidth ); + height = getScalar( origHeight ); + + ratio = origWidth / origHeight; + + // Calculations for the content + minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); + maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); + + minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); + maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); + + // These will be used to determine if wrap can fit in the viewport + origMaxWidth = maxWidth; + origMaxHeight = maxHeight; + + if (current.fitToView) { + maxWidth = Math.min(viewport.w - wSpace, maxWidth); + maxHeight = Math.min(viewport.h - hSpace, maxHeight); + } + + maxWidth_ = viewport.w - wMargin; + maxHeight_ = viewport.h - hMargin; + + if (current.aspectRatio) { + if (width > maxWidth) { + width = maxWidth; + height = getScalar(width / ratio); + } + + if (height > maxHeight) { + height = maxHeight; + width = getScalar(height * ratio); + } + + if (width < minWidth) { + width = minWidth; + height = getScalar(width / ratio); + } + + if (height < minHeight) { + height = minHeight; + width = getScalar(height * ratio); + } + + } else { + width = Math.max(minWidth, Math.min(width, maxWidth)); + + if (current.autoHeight && current.type !== 'iframe') { + inner.width( width ); + + height = inner.height(); + } + + height = Math.max(minHeight, Math.min(height, maxHeight)); + } + + // Try to fit inside viewport (including the title) + if (current.fitToView) { + inner.width( width ).height( height ); + + wrap.width( width + wPadding ); + + // Real wrap dimensions + width_ = wrap.width(); + height_ = wrap.height(); + + if (current.aspectRatio) { + while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { + if (steps++ > 19) { + break; + } + + height = Math.max(minHeight, Math.min(maxHeight, height - 10)); + width = getScalar(height * ratio); + + if (width < minWidth) { + width = minWidth; + height = getScalar(width / ratio); + } + + if (width > maxWidth) { + width = maxWidth; + height = getScalar(width / ratio); + } + + inner.width( width ).height( height ); + + wrap.width( width + wPadding ); + + width_ = wrap.width(); + height_ = wrap.height(); + } + + } else { + width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); + height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); + } + } + + if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { + width += scrollOut; + } + + inner.width( width ).height( height ); + + wrap.width( width + wPadding ); + + width_ = wrap.width(); + height_ = wrap.height(); + + canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; + canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); + + $.extend(current, { + dim : { + width : getValue( width_ ), + height : getValue( height_ ) + }, + origWidth : origWidth, + origHeight : origHeight, + canShrink : canShrink, + canExpand : canExpand, + wPadding : wPadding, + hPadding : hPadding, + wrapSpace : height_ - skin.outerHeight(true), + skinSpace : skin.height() - height + }); + + if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { + inner.height('auto'); + } + }, + + _getPosition: function (onlyAbsolute) { + var current = F.current, + viewport = F.getViewport(), + margin = current.margin, + width = F.wrap.width() + margin[1] + margin[3], + height = F.wrap.height() + margin[0] + margin[2], + rez = { + position: 'absolute', + top : margin[0], + left : margin[3] + }; + + if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { + rez.position = 'fixed'; + + } else if (!current.locked) { + rez.top += viewport.y; + rez.left += viewport.x; + } + + rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); + rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); + + return rez; + }, + + _afterZoomIn: function () { + var current = F.current; + + if (!current) { + return; + } + + F.isOpen = F.isOpened = true; + + F.wrap.css('overflow', 'visible').addClass('fancybox-opened').hide().show(0); + + F.update(); + + // Assign a click event + if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { + F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { + if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { + e.preventDefault(); + + F[ current.closeClick ? 'close' : 'next' ](); + } + }); + } + + // Create a close button + if (current.closeBtn) { + $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { + e.preventDefault(); + + F.close(); + }); + } + + // Create navigation arrows + if (current.arrows && F.group.length > 1) { + if (current.loop || current.index > 0) { + $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); + } + + if (current.loop || current.index < F.group.length - 1) { + $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); + } + } + + F.trigger('afterShow'); + + // Stop the slideshow if this is the last item + if (!current.loop && current.index === current.group.length - 1) { + + F.play( false ); + + } else if (F.opts.autoPlay && !F.player.isActive) { + F.opts.autoPlay = false; + + F.play(true); + } + }, + + _afterZoomOut: function ( obj ) { + obj = obj || F.current; + + $('.fancybox-wrap').trigger('onReset').remove(); + + $.extend(F, { + group : {}, + opts : {}, + router : false, + current : null, + isActive : false, + isOpened : false, + isOpen : false, + isClosing : false, + wrap : null, + skin : null, + outer : null, + inner : null + }); + + F.trigger('afterClose', obj); + } + }); + + /* + * Default transitions + */ + + F.transitions = { + getOrigPosition: function () { + var current = F.current, + element = current.element, + orig = current.orig, + pos = {}, + width = 50, + height = 50, + hPadding = current.hPadding, + wPadding = current.wPadding, + viewport = F.getViewport(); + + if (!orig && current.isDom && element.is(':visible')) { + orig = element.find('img:first'); + + if (!orig.length) { + orig = element; + } + } + + if (isQuery(orig)) { + pos = orig.offset(); + + if (orig.is('img')) { + width = orig.outerWidth(); + height = orig.outerHeight(); + } + + } else { + pos.top = viewport.y + (viewport.h - height) * current.topRatio; + pos.left = viewport.x + (viewport.w - width) * current.leftRatio; + } + + if (F.wrap.css('position') === 'fixed' || current.locked) { + pos.top -= viewport.y; + pos.left -= viewport.x; + } + + pos = { + top : getValue(pos.top - hPadding * current.topRatio), + left : getValue(pos.left - wPadding * current.leftRatio), + width : getValue(width + wPadding), + height : getValue(height + hPadding) + }; + + return pos; + }, + + step: function (now, fx) { + var ratio, + padding, + value, + prop = fx.prop, + current = F.current, + wrapSpace = current.wrapSpace, + skinSpace = current.skinSpace; + + if (prop === 'width' || prop === 'height') { + ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); + + if (F.isClosing) { + ratio = 1 - ratio; + } + + padding = prop === 'width' ? current.wPadding : current.hPadding; + value = now - padding; + + F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); + F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); + } + }, + + zoomIn: function () { + var current = F.current, + startPos = current.pos, + effect = current.openEffect, + elastic = effect === 'elastic', + endPos = $.extend({opacity : 1}, startPos); + + // Remove "position" property that breaks older IE + delete endPos.position; + + if (elastic) { + startPos = this.getOrigPosition(); + + if (current.openOpacity) { + startPos.opacity = 0.1; + } + + } else if (effect === 'fade') { + startPos.opacity = 0.1; + } + + F.wrap.css(startPos).animate(endPos, { + duration : effect === 'none' ? 0 : current.openSpeed, + easing : current.openEasing, + step : elastic ? this.step : null, + complete : F._afterZoomIn + }); + }, + + zoomOut: function () { + var current = F.current, + effect = current.closeEffect, + elastic = effect === 'elastic', + endPos = {opacity : 0.1}; + + if (elastic) { + endPos = this.getOrigPosition(); + + if (current.closeOpacity) { + endPos.opacity = 0.1; + } + } + + F.wrap.animate(endPos, { + duration : effect === 'none' ? 0 : current.closeSpeed, + easing : current.closeEasing, + step : elastic ? this.step : null, + complete : F._afterZoomOut + }); + }, + + changeIn: function () { + var current = F.current, + effect = current.nextEffect, + startPos = current.pos, + endPos = { opacity : 1 }, + direction = F.direction, + distance = 200, + field; + + startPos.opacity = 0.1; + + if (effect === 'elastic') { + field = direction === 'down' || direction === 'up' ? 'top' : 'left'; + + if (direction === 'down' || direction === 'right') { + startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); + endPos[ field ] = '+=' + distance + 'px'; + + } else { + startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); + endPos[ field ] = '-=' + distance + 'px'; + } + } + + // Workaround for http://bugs.jquery.com/ticket/12273 + if (effect === 'none') { + F._afterZoomIn(); + + } else { + F.wrap.css(startPos).animate(endPos, { + duration : current.nextSpeed, + easing : current.nextEasing, + complete : F._afterZoomIn + }); + } + }, + + changeOut: function () { + var previous = F.previous, + effect = previous.prevEffect, + endPos = { opacity : 0.1 }, + direction = F.direction, + distance = 200; + + if (effect === 'elastic') { + endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; + } + + previous.wrap.animate(endPos, { + duration : effect === 'none' ? 0 : previous.prevSpeed, + easing : previous.prevEasing, + complete : function () { + $(this).trigger('onReset').remove(); + } + }); + } + }; + + /* + * Overlay helper + */ + + F.helpers.overlay = { + defaults : { + closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay + speedOut : 200, // duration of fadeOut animation + showEarly : true, // indicates if should be opened immediately or wait until the content is ready + css : {}, // custom CSS properties + locked : !isTouch, // if true, the content will be locked into overlay + fixed : true // if false, the overlay CSS position property will not be set to "fixed" + }, + + overlay : null, // current handle + fixed : false, // indicates if the overlay has position "fixed" + el : $('html'), // element that contains "the lock" + + // Public methods + create : function(opts) { + var parent; + + opts = $.extend({}, this.defaults, opts); + + if (this.overlay) { + this.close(); + } + + parent = F.coming ? F.coming.parent : opts.parent; + + this.overlay = $('').appendTo( parent && parent.length ? parent : 'body' ); + this.fixed = false; + + if (opts.fixed && F.defaults.fixed) { + this.overlay.addClass('fancybox-overlay-fixed'); + + this.fixed = true; + } + }, + + open : function(opts) { + var that = this; + + opts = $.extend({}, this.defaults, opts); + + if (this.overlay) { + this.overlay.unbind('.overlay').width('auto').height('auto'); + + } else { + this.create(opts); + } + + if (!this.fixed) { + W.bind('resize.overlay', $.proxy( this.update, this) ); + + this.update(); + } + + if (opts.closeClick) { + this.overlay.bind('click.overlay', function(e) { + if ($(e.target).hasClass('fancybox-overlay')) { + if (F.isActive) { + F.close(); + } else { + that.close(); + } + + return false; + } + }); + } + + this.overlay.css( opts.css ).show(); + }, + + close : function() { + W.unbind('resize.overlay'); + + if (this.el.hasClass('fancybox-lock')) { + $('.fancybox-margin').removeClass('fancybox-margin'); + + this.el.removeClass('fancybox-lock'); + + W.scrollTop( this.scrollV ).scrollLeft( this.scrollH ); + } + + $('.fancybox-overlay').remove().hide(); + + $.extend(this, { + overlay : null, + fixed : false + }); + }, + + // Private, callbacks + + update : function () { + var width = '100%', offsetWidth; + + // Reset width/height so it will not mess + this.overlay.width(width).height('100%'); + + // jQuery does not return reliable result for IE + if (IE) { + offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); + + if (D.width() > offsetWidth) { + width = D.width(); + } + + } else if (D.width() > W.width()) { + width = D.width(); + } + + this.overlay.width(width).height(D.height()); + }, + + // This is where we can manipulate DOM, because later it would cause iframes to reload + onReady : function (opts, obj) { + var overlay = this.overlay; + + $('.fancybox-overlay').stop(true, true); + + if (!overlay) { + this.create(opts); + } + + if (opts.locked && this.fixed && obj.fixed) { + obj.locked = this.overlay.append( obj.wrap ); + obj.fixed = false; + } + + if (opts.showEarly === true) { + this.beforeShow.apply(this, arguments); + } + }, + + beforeShow : function(opts, obj) { + if (obj.locked && !this.el.hasClass('fancybox-lock')) { + if (this.fixPosition !== false) { + $('*:not(object)').filter(function(){ + return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") ); + }).addClass('fancybox-margin'); + } + + this.el.addClass('fancybox-margin'); + + this.scrollV = W.scrollTop(); + this.scrollH = W.scrollLeft(); + + this.el.addClass('fancybox-lock'); + + W.scrollTop( this.scrollV ).scrollLeft( this.scrollH ); + } + + this.open(opts); + }, + + onUpdate : function() { + if (!this.fixed) { + this.update(); + } + }, + + afterClose: function (opts) { + // Remove overlay if exists and fancyBox is not opening + // (e.g., it is not being open using afterClose callback) + if (this.overlay && !F.coming) { + this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); + } + } + }; + + /* + * Title helper + */ + + F.helpers.title = { + defaults : { + type : 'float', // 'float', 'inside', 'outside' or 'over', + position : 'bottom' // 'top' or 'bottom' + }, + + beforeShow: function (opts) { + var current = F.current, + text = current.title, + type = opts.type, + title, + target; + + if ($.isFunction(text)) { + text = text.call(current.element, current); + } + + if (!isString(text) || $.trim(text) === '') { + return; + } + + title = $('',image:'',iframe:'",error:'' + text + ''); + + switch (type) { + case 'inside': + target = F.skin; + break; + + case 'outside': + target = F.wrap; + break; + + case 'over': + target = F.inner; + break; + + default: // 'float' + target = F.skin; + + title.appendTo('body'); + + if (IE) { + title.width( title.width() ); + } + + title.wrapInner(''); + + //Increase bottom margin so this title will also fit into viewport + F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); + break; + } + + title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); + } + }; + + // jQuery plugin initialization + $.fn.fancybox = function (options) { + var index, + that = $(this), + selector = this.selector || '', + run = function(e) { + var what = $(this).blur(), idx = index, relType, relVal; + + if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { + relType = options.groupAttr || 'data-fancybox-group'; + relVal = what.attr(relType); + + if (!relVal) { + relType = 'rel'; + relVal = what.get(0)[ relType ]; + } + + if (relVal && relVal !== '' && relVal !== 'nofollow') { + what = selector.length ? $(selector) : that; + what = what.filter('[' + relType + '="' + relVal + '"]'); + idx = what.index(this); + } + + options.index = idx; + + // Stop an event from bubbling if everything is fine + if (F.open(what, options) !== false) { + e.preventDefault(); + } + } + }; + + options = options || {}; + index = options.index || 0; + + if (!selector || options.live === false) { + that.unbind('click.fb-start').bind('click.fb-start', run); + + } else { + D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); + } + + this.filter('[data-fancybox-start=1]').trigger('click'); + + return this; + }; + + // Tests that need a body at doc ready + D.ready(function() { + var w1, w2; + + if ( $.scrollbarWidth === undefined ) { + // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth + $.scrollbarWidth = function() { + var parent = $('').appendTo('body'), + child = parent.children(), + width = child.innerWidth() - child.height( 99 ).innerWidth(); + + parent.remove(); + + return width; + }; + } + + if ( $.support.fixedPosition === undefined ) { + $.support.fixedPosition = (function() { + var elem = $('').appendTo('body'), + fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); + + elem.remove(); + + return fixed; + }()); + } + + $.extend(F.defaults, { + scrollbarWidth : $.scrollbarWidth(), + fixed : $.support.fixedPosition, + parent : $('body') + }); + + //Get real width of page scroll-bar + w1 = $(window).width(); + + H.addClass('fancybox-lock-test'); + + w2 = $(window).width(); + + H.removeClass('fancybox-lock-test'); + + $("").appendTo("head"); + }); + +}(window, document, jQuery)); diff --git a/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.pack.js b/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.pack.js new file mode 100644 index 000000000..2db128084 --- /dev/null +++ b/app/appfront/theme/base/front/assets/fancybox/jquery.fancybox.pack.js @@ -0,0 +1,46 @@ +/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ +(function(s,H,f,w){var K=f("html"),q=f(s),p=f(H),b=f.fancybox=function(){b.open.apply(this,arguments)},J=navigator.userAgent.match(/msie/i),C=null,t=H.createTouch!==w,u=function(a){return a&&a.hasOwnProperty&&a instanceof f},r=function(a){return a&&"string"===f.type(a)},F=function(a){return r(a)&&0The requested content cannot be loaded.
',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, +openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, +isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=u(a)?f(a).get():[a]),f.each(a,function(e,c){var l={},g,h,k,n,m;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),u(c)?(l={href:c.data("fancybox-href")||c.attr("href"),title:f("").text(c.data("fancybox-title")||c.attr("title")).html(),isDom:!0,element:c}, +f.metadata&&f.extend(!0,l,c.metadata())):l=c);g=d.href||l.href||(r(c)?c:null);h=d.title!==w?d.title:l.title||"";n=(k=d.content||l.content)?"html":d.type||l.type;!n&&l.isDom&&(n=c.data("fancybox-type"),n||(n=(n=c.prop("class").match(/fancybox\.(\w+)/))?n[1]:null));r(g)&&(n||(b.isImage(g)?n="image":b.isSWF(g)?n="swf":"#"===g.charAt(0)?n="inline":r(c)&&(n="html",k=c)),"ajax"===n&&(m=g.split(/\s+/,2),g=m.shift(),m=m.shift()));k||("inline"===n?g?k=f(r(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):l.isDom&&(k=c): +"html"===n?k=g:n||g||!l.isDom||(n="inline",k=c));f.extend(l,{href:g,type:n,content:k,title:h,selector:m});a[e]=l}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==w&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1===b.trigger("onCancel")||(b.hideLoading(),a&&(b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(), +b.coming=null,b.current||b._afterZoomOut(a)))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(b.isOpen&&!0!==a?(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]()):(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&& +(b.player.timer=setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};!0===a||!b.player.isActive&&!1!==a?b.current&&(b.current.loop||b.current.index
Please try again later.=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==w&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,l;c&&(l=b._getPosition(d),a&&"scroll"===a.type?(delete l.position,c.stop(!0,!0).animate(l,200)):(c.css(l),e.pos=f.extend({},e.dim,l)))}, +update:function(a){var d=a&&a.originalEvent&&a.originalEvent.type,e=!d||"orientationchange"===d;e&&(clearTimeout(C),C=null);b.isOpen&&!C&&(C=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),C=null)},e&&!t?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,t&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"), +b.trigger("onUpdate")),b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f(' ').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){27===(a.which||a.keyCode)&&(a.preventDefault(),b.cancel())});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}));b.trigger("onLoading")},getViewport:function(){var a=b.current&& +b.current.locked||!1,d={x:q.scrollLeft(),y:q.scrollTop()};a&&a.length?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=t&&s.innerWidth?s.innerWidth:q.width(),d.h=t&&s.innerHeight?s.innerHeight:q.height());return d},unbindEvents:function(){b.wrap&&u(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");q.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(q.bind("orientationchange.fb"+(t?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c= +e.which||e.keyCode,l=e.target||e.srcElement;if(27===c&&b.coming)return!1;e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||l&&(l.type||f(l).is("[contenteditable]"))||f.each(d,function(d,l){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();0!==c&&!k&&1 g||0>l)&&b.next(0>g?"up":"right"),d.preventDefault())}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&& +b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0,{},b.helpers[d].defaults,e),c)})}p.trigger(a)},isImage:function(a){return r(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return r(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=m(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c, +c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"=== +c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=!0);"iframe"===c&&t&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(t?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,x(d.padding[a]))});b.trigger("onReady"); +if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width= +this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload=this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming, +d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",t?"auto":a.iframe.scrolling).attr("src",a.href);f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);t||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload|| +b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,l,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove()); +b.unbindEvents();e=a.content;c=a.type;l=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f(" ").html(e).find(a.selector):u(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder", +!1)}));break;case "image":e=a.tpl.image.replace(/\{href\}/g,g);break;case "swf":e='"}u(e)&&e.parent().is(a.inner)||a.inner.append(e);b.trigger("beforeShow"); +a.inner.css("overflow","yes"===l?"scroll":"no"===l?"hidden":l);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(!b.isOpened)f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();else if(d.prevMethod)b.transitions[d.prevMethod]();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,l=b.skin,g=b.inner,h=b.current,c=h.width,k=h.height,n=h.minWidth,v=h.minHeight,p=h.maxWidth, +q=h.maxHeight,t=h.scrolling,r=h.scrollOutside?h.scrollbarWidth:0,y=h.margin,z=m(y[1]+y[3]),s=m(y[0]+y[2]),w,A,u,D,B,G,C,E,I;e.add(l).add(g).width("auto").height("auto").removeClass("fancybox-tmp");y=m(l.outerWidth(!0)-l.width());w=m(l.outerHeight(!0)-l.height());A=z+y;u=s+w;D=F(c)?(a.w-A)*m(c)/100:c;B=F(k)?(a.h-u)*m(k)/100:k;if("iframe"===h.type){if(I=h.content,h.autoHeight&&1===I.data("ready"))try{I[0].contentWindow.document.location&&(g.width(D).height(9999),G=I.contents().find("body"),r&&G.css("overflow-x", +"hidden"),B=G.outerHeight(!0))}catch(H){}}else if(h.autoWidth||h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(D),h.autoHeight||g.height(B),h.autoWidth&&(D=g.width()),h.autoHeight&&(B=g.height()),g.removeClass("fancybox-tmp");c=m(D);k=m(B);E=D/B;n=m(F(n)?m(n,"w")-A:n);p=m(F(p)?m(p,"w")-A:p);v=m(F(v)?m(v,"h")-u:v);q=m(F(q)?m(q,"h")-u:q);G=p;C=q;h.fitToView&&(p=Math.min(a.w-A,p),q=Math.min(a.h-u,q));A=a.w-z;s=a.h-s;h.aspectRatio?(c>p&&(c=p,k=m(c/E)),k>q&&(k=q,c=m(k*E)),c').appendTo(d&&d.lenth?d:"body");this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(q.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay", +function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive?b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){q.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),this.el.removeClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%"); +J?(b=Math.max(H.documentElement.offsetWidth,H.body.offsetWidth),p.width()>b&&(a=p.width())):p.width()>q.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&this.fixed&&b.fixed&&(b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){b.locked&&!this.el.hasClass("fancybox-lock")&&(!1!==this.fixPosition&&f("*").filter(function(){return"fixed"=== +f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin"),this.scrollV=q.scrollTop(),this.scrollH=q.scrollLeft(),this.el.addClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float", +position:"bottom"},beforeShow:function(a){var d=b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(r(e)&&""!==f.trim(e)){d=f('A||z>s)&&c>n&&k>v&&!(19 p&&(c=p,k=m(c/E)),g.width(c).height(k),e.width(c+y),a=e.width(),z=e.height();else c=Math.max(n,Math.min(c,c-(a-A))),k=Math.max(v,Math.min(k,k-(z-s)));r&&"auto"===t&&kA||z>s)&&c>n&&k>v;c=h.aspectRatio?c v&&k '+e+"");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),J&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(m(d.css("margin-bottom")))}d["top"===a.position?"prependTo": +"appendTo"](c)}}};f.fn.fancybox=function(a){var d,e=f(this),c=this.selector||"",l=function(g){var h=f(this).blur(),k=d,l,m;g.ctrlKey||g.altKey||g.shiftKey||g.metaKey||h.is(".fancybox-wrap")||(l=a.groupAttr||"data-fancybox-group",m=h.attr(l),m||(l="rel",m=h.get(0)[l]),m&&""!==m&&"nofollow"!==m&&(h=c.length?f(c):e,h=h.filter("["+l+'="'+m+'"]'),k=h.index(this)),a.index=k,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;c&&!1!==a.live?p.undelegate(c,"click.fb-start").delegate(c+":not('.fancybox-item, .fancybox-nav')", +"click.fb-start",l):e.unbind("click.fb-start").bind("click.fb-start",l);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===w&&(f.scrollbarWidth=function(){var a=f('').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});f.support.fixedPosition===w&&(f.support.fixedPosition=function(){var a=f('').appendTo("body"), +b=20===a[0].offsetTop||15===a[0].offsetTop;a.remove();return b}());f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(s).width();K.addClass("fancybox-lock-test");d=f(s).width();K.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery); \ No newline at end of file diff --git a/app/appfront/theme/base/front/assets/images/1.jpg b/app/appfront/theme/base/front/assets/images/1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..de17145b4108595e5d7a7b3abb76f9a1557a3ecc GIT binary patch literal 22606 zcmcG#1yEc~w=O(`ySonV?(XjH2{yPxf(N(YPH=Y%9!Ma#hu}_dhv32aC&~MM=loTt zZr!?d@2X)>_j;Ch_nw(%_shb|27o}u%hn12P*7k5AOQZ0UXB5n(r+y6y#YV~41_HU z0K9BK2iSOcxCpYbIk~f%Svs48SuLC$*}TkL*f?0(*#N>~UM^-9_FxZ?IoR6PNrdue zM;9f?)>4F0k4J@F#YGBiV=M3D2G;UX)wb}lw-B(T6cYsrdkK0ux;TP8%s^g_4o>cZ zULur#j0-~Azu9b*pg$rW_9B!LzrBL=Rn$RJ&Te234=XQ=1v@Vvh);l(gNKign~xd9 z$UXCCJS#$ju4*hbST5+$^mGHKk?$@dfFLQ2vvYr>7^YCl{-;n>8DU zfPerSJ0}|_CksS^#ogPyNa%hbH*H!uTJh-L<`4z-*decjq^57GQ`t)xXM++WoH`{T75o zBdF$P3mFtM2We-EH;!N@4+UuvN(jPgX=^FS#lZ^(TXLDP@R;$kvw+RGxmozx1uR(1 z1 8;48MozZ`RUaH`}*hOIbH(N6?=-3)=n O3GlG+SwQkP _!rAT#oJ^FK=g()rI~0y{xgkQ-#F zyqp4P|11E2 Ks(g)aq+)se8K;VDfX#lWLzvBZU{QsDLa0~zd4hRhe z3k?Ma1^tHugvi2TVqwEk;9!8*#VI*(;i;(eB{;dbX huu6lNs79#LCfN-ha1;r As{pi6g2R6tUv%J#IA-J#ALxo4DqvW&?NiDdA>{F%Mt(u8X}De zjR}$Zx&B-I|2E-`%4`-chRb615h8d<+5BrB*(%iU*$xce9A1aD3~J7aJfIQ(i{Yu@ z>~13#;sMo}=;^r-d-T(3;^Lf2{-D73?$cQrut~!e1cQNBS7+Z?KUhX(8gMF1muG!c zhv>scFbcTVW$a9YiU+7hVQFMG4>aDt;@eWEjkOu2Rmnb-y@E)g+4 0dby{SFHn|--1tX$x5`LyAToER(}5y@v$Nu}vm8#uEt32kZg+3aafCst*t0N3 z(I{SsyLeGCVdh-2kguAWh#>)>apl9%ZW!^j5ryeYvJasL z9SI#ZW}l8+$d%o#5j4&@WTDGPiL(kEMY-Ic_5c7}E~D{Bq5)*kJ;}B-s2JE076Kn* zR0+ew9R_(>f)Cm-=`4jn0O;MVtdtJ}4C{b1ENa^Xm0UvFF?-o5`vHnNEZKTpBVj>< z41XdM0Q3%(8V6!8PBHZKS1VG4AK$pac!-w>G2EO7DRSwGqcR~*LWEt(>(IShJp^&I zNbk`l4i4DW-)f~|z{*&5I}GzQfbd3l%^EWX1R8Vdm%qX`ZfOBxXktQozoSN`^I%(1 zkNXve@=-c$_0tu*N>C%i7WG&j!TXB w{0M|C1e`^Snh6Wji-z+gYjB`I7ZMfV*$+z7s36QCNjMC%rbUCPhlM@03Vu(7 zA-EP}R^kd)cX#$dLGK}yX@WssDPsnfbY*uho@A6>I<)e)RF;sD<~QqC>YtL{53e@O zfKz~aMK?}ALN(SS-11s9i3(B6n-}{#L<*Jv&T@zqC&wmM;8R0pg+@yvT)DGVt}z87 zCI9`(nm9xR0F80G(5Y_1%h{;U=dM79DnCJm+SbS8&Kyo1-=y$c0stT<&M1+Yp7NMS z4UM3T9$2@vQpmLn4a&62GYkAHK%NNOvvHu|Qg4+McFDd6EB%4QG;6XkPv#$-I&;xL zod%@`VS<5IlY3ghEx0?*aZgWh=#M(^VxufI74RmQWH#2JmqulK&$1iC5*z-lAp1Y~ za1}mq!{Boku!N|)KDo3|Qz`o_TSPQg@DC0EUU*lAFkcZ`tyyLdrSWXaFCwW>FGji_ zH2VD&5S0ZfMTCV+>BkEe^rHpafs3rU-6lniMN4@D|42Y@Q|WRdb&CrNx>k@ =G9(%yNbpA;mHRHTL0eyhIX4}}ZBgO9HW+Fcr0dV_f$;|>!n{ !Z1xbu6~{wB&;{(1S}MUPRgu?FodUdr3Q?EjZnAmo$f z_s1j<7U~6%G1CNkF9nCFAO`J T+p=O z_V$CyYDyI%k%S#Z2Z*eQ*g}4a8{uQpVb&Y_RJ~z#gkhQEl{YOKLdo?D>0m~)3IjC1 z^q_c(7{c%mJbB;QQ(6?%!z?&IuV2`>0SO6xeh!&)(z!KJD>V2Rj(fvdP|O^>P6x7t zc<_W`il&5h)W^4RV>2LQ)PTS8lVp-4$SSgFPNdoTm}J#eI9EuyiWf5nDZqo81r-c3 zCDMZ^#Ipz$fjktu@@Fa~^XX)TA{J~z$=19h=*yrID+x|DEw=`c;Ygs%or>?s)hGY< z{QmjkSlM?DF$pt?DY2$gyQ}`f)&yzk$BFpw>4lutRG0hh9V(4HW;=Mhb+IO*KX2j> zR!@COB&{*=yID>-3d20a-;vZS@@L;$@p1p41~whE)xg5B86VwA!XvK!)P@wVCC`Ej zrg)>BI*2wB*QqGF;i+Bn!-!cj{5rd(ZJV^_fV)b-z7{7f&m(Ft3sl%E*-Rsvsuag( z^+-Rpx1ti$(I_x?X-~hUmvZ2r?N$`GrCVKQD_p|N=~uuOIvDMW*VCzEU+?g`P5@t* zv$yzBKcW_TU>MjaUIk>Qst~Xs!+!n9apgX_9gX|Tozrtpvv*NU9(NOR^{n}4^5+z z?a*l%oJ5&%%x0dIFAc8ieE(t&k#*JwVW(FW(q`}>uk+np0gS>ah|0t&YjR;kCb+@* zO4}zNq_$bwo^m$7&vH5zNXJbrO|sqm{FaV4BIt+0yZOPyy?WHT^ X(B^Qm#kUe!5#;xf z6~F~YKQz@gWM{;~Tq_*FTym yV-M%(_#ywS&4N7`7x z Ua{A1CUrZe zJu&1w`Z`9kW_6#8>w|WNrbQQ`TnHKhBO6IfLIjZgu n)-<{^gTdzySJFc&>ZR8Q!Ap`J;}4CC+RFMKB?pW&BTB28^^e#sb-9nQg&FG-rW zx$==rIy!CX7)lR5gvrNkgA4kbK51DP)T?#kuUIZ~L)o?>bkeD*x*wrLvPdU5WrWGO zn==KF4sjUC=xM)-7Yn)gN=bl`HtPJ8Gm6l4zf;?Rh`FLHU&d=vo%BI?= ;c81h}@w1~T6hmg75E8Eo5gXG$t) D=d-E4*rJnO^OZgnkvL<+g zRRzNQA1t#HaT;d6h~zs2Y(!iy0EgGpqVCvCW~2P7{xDusG;I$ImC+n2A6bo0=Im4C zaA$~BC0`G1fp%Q?tKJ pot cA#rngQA&Bk89JpJ2sWYL5 zi;Xb)91Kgz?YCjYTMKzdI^?I;)l)A31l3G7i{b68^uDINMA{@R%-h_w4g*Kq ?i@{ Ew#b?o$m- zS@07zFoAEdmkqL3a#H1kia=Go1!^uy Zgyn=tfb@?FGf%X>iJfmQ|+~!=?+N(ZObl+SRlwZc9;`c05&p$Y7mdXEbtr-AZ!P zi<`w6d*ppF720&TBBC_Td^=DHHO;i6>II#pTtIt5+^I(YR6#x_bugzHs-pf@X{x3# za>RpOR{>gxZS_qbZw{iF9WislG9`if9egR#x(7vd#JB`ah^>!OVSJcam&~z%!B+g0 zhUIrb`qXnGofzgIK}#N9)2W~q@u4JCS<@^om_-bZ$0^IuhMp2~bV=gM8 YeA@F`8(o{e=tD?PsJ<4iC8)IGV=-7k znaUodz*uU|B;rsW2Jz%TGin2yGmR;Jtme4~G@sp1J2R;yF+|4lD_%~5d^yDN1W#H7 z>Qknf>dTab3b0IoYXUj(1wN0W;73YdH1pG)^J1|0`Sz6QGDnNlrj#bIEvUT+CeY%p zDL=dX)-AHk7ftfZ=noPvONMDAqi}Tf?$}0l6^w2S_IIcmwo;Lw 24F`^!+Z=7VZ`n%r?TREe| cag zziescD~vQI5y^MwKSpeX5GmUdz^|L}qt?|S1V1#2#4P!YLM4AaGRE@4%`#WPU7@JH zOdnD+SpS`A-`NgtT7(G2UtUiN%X}f+4q|`V!kq>Lk0ohlXl`Qz9JAeFTr|cZEya zqzXuS8L|U+)4w#1Qv4Y4wYe)4)N0{Q9mP_Z>pN%SVnx|?H-k0VXmK*Rf0A_D9rsm| zGL42~?{3#8jw$=iKD!@9D+uqhpV1a@qccnbYGR3a0++pTd9L@3w?!d<1FxKN+5rx23h7R+s Mqtq-f=JJ;yW0IsiYmHfq_Yfux={#_p+}N>-_D!7k%lWBt$z6qz`hE zy_%|wUI6LRG?|T8sf-CDdzKRt*H4)?wquoydmkjPn%G46WHn65&75fxEu90DtEiu^ z$`ETd-$ Z*T?`2owyg>0ZQyT=ac&^@#i8Vt43^4+FX}B0zOXw`ELd$p*@= zL50w~>4tt=1!nIurYOr+@R#DulKBLOy%*}QW#by=K)O@FbyI-jC-1KZ9{^4#S<=Gp z6^&Fws&PLgd;x6CJZO^jJi(JURQk9};(oGUb(#=fzkEt NlH-F#q3TNG$emK>?q-C{31w)WTXExA*B;pHj50-+FWZBy z{EWs+EvOaaPvIByC8Zp;jFr$jlspbgl|dekPr}zObJg2O7e(1mr)?|3%6*io99@}= z{8fC#My)X#!$W6E55DR}_QrcI@aW8N%u$k^(V{oy!5R(^y`gCLeX8-a-D~y0#wFdU zPvi9;tDjO?52v<*nyHs?!rlgvOe%HTMjW?!YhCLPRgdwZ37?_0N+v8Tn{E{@zuV{Q zZ+!Q0EfD@r6C}7@$s|^BT(&}%!3JIvF6uC=*4?bdIBZKlwf}K9@e8+rh;tB6QHc9k zlUopld)gz7H?+{+O>2ZlI>-9WuPOJ))f(MbqX$hTa*u{op4w5+7ptUUm*mp8>?wo^ zs 5OTrWuP!}& z6LkHh1#CjyI<2ZvjGf}meLdm%+22rrs0?f%n!}3$J}2#5vsuxmkhdymW_%pdP{|Lb zr6X}GHa;q*TeVXNXT((v6WnxXu_KHUVJASPY4%)NWXGG@#$D7uX12#LEH6uyt|o0s z@y95`?qh-91}hq;D_qK+mk#{8uj0~^;FF56lIjq{%$E?bI9Rz&QRH&i%yoR{b cmmUw`jox{i^!ugq_*&*;H z5$zmr@C8t$&8cP8dT`((df#M*^kyfWRL|C~DFgTxmzsszJk?ktFcs^Gu4yD@Xf7F{ z+{|D}KNFX@GPMGAKC0=gMRk>uTSf&|c1cp9EZvgdm)d_ihMsKd!x~eLUA9)-k^5E8 z8dsxCeI*Yw0~2`^5 @Q)^l@Y~hL{JtWB>oqn{ zRpleCv^Ys}RzFc~yVDYKKUF2zh?!?n`>NsR&8L9HFLM=YA^>w?K1Cr~qVe%8EwK-+ zq>Bps5d>vmkJAEOO7BcV)DcyN-4Gd#M%9aka;61O=xNt*yFsVa?GIZtQkIH3h>}Ez zT+}84QYU4n+;MFx^qM&g;>zEd+xe=qyR9B2g7g$UokF-+1pQs!7svj ix2A zEpvN>p{a=%ViCzNslHr^Q+q=SQ+8>Okt{IwdPDEi(@I_fOy8h=0;!m3d!c1QQ`5pv z=A{7okbW}dApwS<9=*En6mQg$JDd@hN{EvLHjIs8L{b%Wtrq1OGsAv_iRzbari`LZ zwI}t=vFkUfV)xnB)S3xZ&V77!tY1)T;_^`IC^*IW wgD=vIivaWEI=OU+~Y5m!)U0Zbb6wknVl_2KD@Mq|VFwH&x zJ)OD6VGci3Eix?ipbz#G45~>^VJ>qiI7e><4?ZG{&^D8|XV|5MVk@cgX@A+nYqa~; zoJY+grJ=d(q{WN1iP++`h`2h=?V$D+^^o=&b2pTGCmwIARbz#ziLMfFxnfO2lyin_ zjey>NBPjM#NP(9>%(!V|x|ZoV6^yFal-~}HVrZ?~O^h%q9$8u){o-R1N)1NLg&xJ` zVVo!~v+{QjQ85fA(HnWgxXA8CSjrPgbO(KPICSWcvndC~f%(u*&H1ybsnmw9a1z_5 zRn!7|%%Oum)G0F)>uuxP)N;jrtCG~+Qh%Dpif(6<^;<^WKxM0+Dkg6)^1N=feS4rJ z-`CWufJXSo* OT)DV_la%s9c_s=jJ_ AxI|4h*^TX!`Dm+V(CI| M@JCa(vgL6`SkXmYd{*Z1^LbvFu zrKf(~Tisq-d26N|DW2$noa$K%54$ 3EsZ3>yB&u*yY%<40m1RR_dJB4feN(ktD%MwO<@1fsnWQe7jiYU9= zT*7(iKw&O94!4Ep#-D4k-ZA)E_WF!VgR_9U)Jmcs#be;ombrX kLeb0&xHd uE*G**m1Iym$qQicC^hrLRSKnlf-bLij$)r}6bZ8kMjW9&B3hXU z_WMqg#Z7M61*Bi0>)UDL;hI?6EnH=dF?K=g3zXj?y~BKA7=#DAM>Zv=3nX26&hFjR zZl;Na1#^8oZP_0@s!P~7`Nl#4yoq6%GKn0nI~ v9G0Y&>!;n>o?!X16hUeLGv(AK zBX-c3>~-+#TZU)ETzKZ@5Dm&4Ps4I0S )Ce&ZailK}d8a$tro$HQ1wj<8)NW z-7O=>KVSIly=Q<9wypc;5Swe+b9knnZ?438N0@~yTtu6r`SEZIBP=dAl2*!FN3BSu zC2vwn9NIa{`Gtz)7G^c674oZ(AL0xJYsjEuL{kOVTuP_%%;=hTdhn%f*X~m=G_qlw z=9%u>w~Pf0OwF20YQXlB 4`_%@a8NLOj>wG_TgvroI?Qmh0UIf6%tq zbQqsvn+Kx#Dj-WnfE9H5B#j*nj3qL4^1mwW9ULawP^-YJd?%jBg4u0B!l9Nq&+HHK ziVv?KJBW#nW71x-)==uu68y NZv0#(Y^w@o_-R z>MNT0VN13M-Ejqfl5D1@kE2?kXz{zr?}p_wVGplEm&w)i`TQiKC{X63jr{Y>ef&0& zbVIpE98DC{_#_0aQ6@Fio;uUK@f@^jnVL4Pq;PDX-h{eC2PBcb5u*@8%C@onl5&4X zQguV@it3*Fjo-eC922HMbaU4fH)e>mctt*RXs^t}+HCE@--3XmX&0m%R0uG9$K8;6 zus2Vb#5_y1X}wEFN=fGN+<15>4@JtNOOwe%U(pn5Whl|27ld8zdKhNGV@clYoCYi@ zv_&FYGafnOeX6l@Rpg7>lj#H!S%l2Cf_h7J6jF{I6eNM*p9`WtPNqRdnmD{c1Q-5F zMa< ;Lvok*I=mIBFIwE*Y%W)ew66D(X24Kljc)Ua3tl4((~6-whKmm zkB3Pve?49vT7|QTo`&=qE9HBqMP$s$mWQVfAs+QE9FmULdy4l{#$vJ3w;^LM01YHH z{g~2ov;8xYjoCVXeyJ`E RIlL-C6r|Qi^zkqz`q ev ho&&r5&-; %Y&$`j|X)U&$_Cw81`!Su8w^+Mor&W!IF_G9V6ZCjl6z{biT<%>0 z!#k$FD9$;CwU?=ndh&GYY8MayfwMD(h57Hw>|Py8GiIjXG<9VjJ}43azDgQ7%~lUn z8HCd>A9JpD-q(d;yYiCR$bOKuyjh^*Yd1>|C{b*FrU4}GMXcSddIkG`g^$ujJ6F8_ zE{r2MnH)(WFW3iiWlyt94jxu++R^VJvkswPbp08AZAhCRnl*5?>4ES9aM?_@%e%4- zi)(iw3T61d;0QHV6B~*G|K!cZy^{4@c%y|}Rj%s^<>;QbC_ZI6Uo9`Zp(w|GWr8Tt zVB~^bAnLWczNwaktHuWY_?@?a?( vG{wL^h|!#kMB#;*#R?)iij*eL^)uAOfS z`lFveEKXEVuC=M*lsjmi*|F=$sDOY}*V@977_F;9nY7L#eKzD?YZh-5bLP>lM&1sH z`5P((=^1_qGaR)#QPL~q&0Z4-adh-{!u$|`7TXvB7GBapIlC9hv@=UG|1LBDknQ!P z-royLy(z=_w#uiyC>HM0Dthy(iXzW{V)vYtLhOi~J*tr9jIdbcCo@$MIW=9F=Aw!M z^DsVcP(yCKFlAz6%K?I`ek$W^o;3H;4AxW%)NBF&9feAhnm*iNRygRzTvN0*}Fl5V@@NQA&Ff({EMhz68Ft!HlSW8r^a!fN^;wN=~ z<-f+l`?k+r0A_SEx{jW$$`p;u2A5fGoUmb;CSPQo*v}G@$a;2U3aqzvP8HGPW!MYK z8##v0?A%>I_N)0*uI@KOX$%IA9ZfcM>UgU>k48Ez=#z^m9}eO!e0$g$Saw>l#w~){ zQ&1|IKC)6 `B=ROwU-PEc?5 z2udpmDL&K$?QqEa(n!BZ5|$Yhiefy(%vh^ZQ&y1Tbcsze5|#f#H%yvGAD_Mhc}0Jo zj8F)zK^iH>C{8SvO!|DHgIbzn)t6kLz%NnzhAX>tyRK)|^~$?M?LBxJ|KhksZvyLe zkM&YoWC25mhp_C&=Od*{aZDN$LR@E$j6_0Zhh$NeA_}4{D~-jtF|F?f0#dqdMNyM@ zmCPh9ugTj?awbuq21&$s;U+L^e*vB;hNViD_-OmpYPeJB2hXjn=I+ z5(0JVzs0Bt<4}Gj)ybv2*R8-u!U!rcD75XQt}5d4*GM&|U2K##!bdnp_{bTp7LIf} z31p~8sN~9n{P?3kCxR=peWRGpX%@Lb;HMvSkD2SdJUp`iPH7(BG-w$sA3&d}qaq zhvt={!}dk9ahr@ve!{hc@zr^HA&u7nuiz){K`U-I!}1fE$Fz(FmU`KsA#Mbb19^{r z9loo% DTzO gPnWzw+GgO7^!KSRQ;S>K>fbhBw);9ah}$CZbyO7PXiZy^lpH zkH(tH_H_%J_}8YAGZ*Q7%tuvY%qQs^PikU=oZ9rTjenu$w}fS-l-TT^v#m}Q^sc3( z&Ve$m*G$*xa>V+vOUrGa6k$tzr2TyO+ z#d56okzNd;WSNA>C48j`gw)p%XP zL@vK8cpXLc__1kZ_1B7Cp~l&*FW1BH#N%{KbxYcG0SLJL0{E`?_aEZWKrxCJz>OG} z3jCUX9QH$=bzgv5Gr!v2J5QoTlXtEWOJ9mkm8dEQ{Ecb2B_makRi#aR=Ed4Z0@Eds z;i5}AYPxJzUfon(h6HkBl4{$ry+!Zk&`{GrJ>Lo7qMYL3NAMPR8_VUKD0yC^A{t?e zini3_4BtbzQXed1!`Mf)`6y=FP73hfg{hqgUA{?~I S*l4`hFjQ2$;G$E*iTIryyA@OoBBt6Tqz^izh>R$b)4C8x=lOk;rv zy4okJdX8P9TRGwTD27cc_3T2Qy&?{a344S6hwbpl_F$Vc)PRsnfl{Z^9si<_VQsU= z1X2=l`3u#!TUFnTO#0Znk(~;N`QNhpD+z2IyepPl$!}B9K@kSM0OC6MD?f(q&ia2= z(*Sr#iy1vhd*`5^YI!|=D;#ybGw)d_f`t{08CecJp$n@w)4yk#4;!-3%Q!>dc2Ns< zryag9NVJ@lAxrVE@eVxj&%6ZLQ%q+B@D;AT+iK{r!oBl{{AkM`d===QSbRNCS@V;& zJ#)sxWyiZtkV`1 htR>AJAmMxvf1=zl5V@1g_f52Ik=XgUuY8W#PuVj3 zhJAvIOFo#ZhKIH3OY)Zb!x+=Bi+92cp!hP-YJvy5A$o+@jVUmw?Hxd<{nhun^3cY_ z&g5ic={U@}WjMExUVvhhQQOD8b2PDa=gQer3u_^?QAtts%Z%qtYBKz(G%BKvgK(9% zt9tMihcK0e+*Lm%Scd1i&Rzf^T%Wz7-z8s;VI=}5o;z $r$-oB8&G8j@42r30x2e#UrGc#O6Rt%BL_%fd4$ zPQhPuJ0pv~Z&h5G-O(;F<2gnT4}Z$PS$o`L`!NUV?(aE{y2GS}t`&n`*Z$&M)+kd_ zec7it;UUHfPh0q1hg|&r7o5eymJ#aDfZf(i@~&eJ9%vW2OJC5$Bh>DA!_3nj&$t}5 zT`El|Pcy%0GKIX7(OocHv|jfy8qLG54ccttd8xVhG}&PBlq>xfZkwm<8ON@9=A5ac zeNd0MmQ$l|MHl0b*}!EsFQZPHZA9xp_{6 B)L!q3kBg0}4Re+elir(=xSOL4K0041iNE0%RrgnT z?fH{|@PaCu?bX)yJ#V%vawap`x9AIUly+21*ITjti5Qe9wH2BdK));|N8t=xMY(3; z5TGuY9`Gx=MVmZIrBsZas`ORt2}zsp2Kp_Opa+^7pH<12+*Pa(0f`4^wng&mOJ#M! zzBnadP3CY0<#)v9ySo 1S4$7XVT!qtIfB;-mL#%hsD6 zR31-n{;`VV{v~t{sU&lEsaXF$-);t{UHUekTt51`q3eJpCgxB_j-Tl({h{J5GsmSa zmd+@3UMt|GDKh?dlu$o39v7v{H%vIIUabo{&sh ~2gXM;?-EZ>o)Df>@6EL^k?jkvquvQS;ck6gsg$u?Ctf|5B+HdjTtjyBs!9n7 zCzp jbl#J-4 zvWB0HEAD-0dh?gN`WUUgRCAxvD-_A51?u)?U>0KNs2GsB_P5BB*2_{+p0JP+%-((0 znJW=8gag*X@`@Qqx$%88;(vs{O=`DTZ!0;zPk(rqZ51#yqc*8oC~hD3IV^eiRj_2T zTX3AmI6^LKS*qjMS99>r6yCDCTPQi|z-Z;&XRKNZrcW*T=Pr^T2Qxj @D19Y^tCp_w5qZw7k!o3 z_qFcp$q$K~lnoDWM8i#4oEunwaz0|+1^GP{yN~xS`_IU`$R4d_;DvqO90-YUyc7TK zDdIZslgto1D2VKj-c@QLV~^Rxnu^Z6>^D$5ojBlf2d}`|b+BG>A-4u)%Xf}N9C4C+ z^fc&b+V}|d&E`Ax>p2I^t2k0R`H`j0tQ0}ot!%o*bexom?HOkC?`&YHz;&vRf$huG zhK&Q*N!!coYmR5_eb#Utj>aa&%QX~NDOH}B&0B+M8tlM*F!H Y7j=hj+~rY;>)wbO1DM@%+dOEvEwy=AJn51A$igF0>yg@S!}z6TQ~U#t z*x`H8eQf}^6aD9R`UiHRMDMnqSzq%?Tv?pTv!E};BElt!ZVzn%-S&^~6r0+ZuO_^D zBM-`Dq2OB470TNNaeBJ9nCCI;9VP2{P-k&n*(rK8&hTkZ?3YZDBz(@t#ZY=SJ|I2g z v2h6jv2zwW-N0P%|fbnja2}( zk{im)%Kibv(RE$sp!GUyBvz#+lWu~50_94A!7hZwb&vBFDoEbN_n7zv5Cl`E{L#5Z z+t(k_hMxYB1x9`Bb&3f+G~wLn+a^<0VtC5 udZ2T#GOqL*eb}8Q42OKl}W-P4opBywV!`cyumd ztIF@e4TI~kro|76Gxymj&fHsLV7!rePu}}?<>UT2{YrE}on=$T2-Ei&YQX`AdEw4w zk2>qIAv;}^e!W+g@vC}ZQmS!s!s5Hp@x&5~?c+czQ;AkB$2WSsZNPQsZ}Bh#h3#%N zk8q~L_iY8Io#pIZhfQa5kFaCRAR!yI=212ENkz304BU$3Lh4y}&G?V{x+&l~g-)!nf zuj4tPY|8jbS3v@y6`14lg$#uYk9*U1uV{c7o!MSFiAm{6+z%P%aTCALYI-kjA=^M- zY2-FdUjX&fH);#mgbe v_czu6t5MFizF>>1I$0wh$nf*&+C6%*WKUUe(h07Re7=t zkZ`r=>Lsx peE!Wn{+)t*8A{Q1{ovA`kebIwc|ax58Gk;SIt3NU+8{`Au8yVg4t7zw*Cmk zYus}ZFNywyUlXPAgoHiE^0_f&$G0B{bh1 ~c=cws}M({D}u%09?{Y zJX@GPkyir2u #d)IyF)|~5uct%3aK=7Jvp9mb5UCAEb$w4iLFunWywSP1aEdi zLR^AdTJ`I{taMaJ1r1Q8r;oIVWC(>ssT_5%F&yIVeN?w~pY%<67AiD6k7!!EG&-r+ zpRcZUXhvLevcMME;(4ciuViE!z((FMP6D0(&dK?;{<{E~Qf*@a^nxnxb6BN&=g_XG zGzwEwO%lcn@aTp?hd`T>*S$D&b2oQct20(>h%DN`&yYBM;^-dOI8p@iO8DgdU!H?e zTEj7lKgsSdde+ug56RHoE$#dW7&TtAAU`FGt@@+9j%r@=e*rXD=D0s5(``n5??YzZ zfum0eI{5VT-IkuX(2u+wUCOAdDCL~Y&9-nkK#HwDaN6rrEx9!9XbdW>zP-O913!6u z%nXaXxU1R$ljw#Z25e&eW0NBF?)@_g7XxJpUPJ>%0J>O1i$=8$0-h|{i6G9~$n9ZV zYSaLj)35gp)7RPMR?^cH*|Rr%7%k;!^IDSPEg{aEG=kO H r?!(Zkd?IJ=6*B mi0eEx(Yr7tpiJAqBKT8}oU-OuOW&~+3?aGUTd01 XA~h?g=xkMJ@xsrq`mm7Nb}C9ulgU#<2fyg z=yTRD(FY2`SyEW@eApPStzl~E92oCx(9R+$rhbh*sV#&>Y%{+DkALYjRmPe=!q|KV z=BlL1Nc%CvZGcW`%40p|64B%K>uZ4gjF!oO|51e5xD=B~dqY?J!sR;r))>jyFUwYi zD7`*cMpcw;`m~cLPL_S{9~_=sal4-;+kS}z--wy-Up&LYd|)Q*#Zzu&aE$8lra`TT z>r%_MB>*cPVOo4WwaQ+4AYb5BuEXg{6X_# lH zJ^FyE8=5vA$!fn1!y$QnTqFH^s){eoH*tnRk$Htr0g~N3h@`uivT!@Zityh?Phd-$ zp_xyi877X?QT@~^^FE*Teei>Q811#{ti ~MSa{H#3vu0sS>A}iCX=hl3t)tZD3-Fb{sl1HJ1h2#^!EX^ zzuPURmw%s7`)|GfI`#JV%*g-kvk>Cc82=pi`E5B601E!c0}Pe~brJyPAFuL&B*^JI zaq8co1ON&FCQuyk7fO%^VTe;hDL`}q07U8}1!^n_7z}wxhZ+M210@0T`wX=B?`{Gj zHI_IGKptWQ1OS4P#9@*UseeNX)JftXNElcUNdO390b)Gxk0KW0?=XS^)KI|Ru7f40 zu>deh3J@j$OB{eD0ZM>)K?DT?VUpxwf)QZ?Az?ra%KwfK3kZV&u@3-X$U|%bk|aRE zf1(1&gMtwt!Gj>sZ<2t4nEFH17!r_oh>Jgj2$LZGJCZ*Hg9V@lApVmw0D&4x9)JP- z3jrV%2nPO1|2G4Kg+Lwr+s+??#PFZC1Rwzc0FnGdFo8hoBt#gDzdd;vECdk5=06am z2;$U%e|r*t>h_;8LIePSpnss>Ljdz1gOIQxqwtSG0Cg}TDCu`SAw&(3hXMRMlu!yF zfCT8@yr`idNr^+y--Lw-8A=eOhJOeKN&zMi07&@TgE*3){@3_Ftp6u(=>OSDMHS z@`<;p>Wv^qS-d_hx*g8p9A5+30b4H+Svj(vGtzpE(DN{u$fj`SEQy$20K^(LbUpqs zTEwOB)@`c#>Rl_i@Ztm~R!)O+ZIfZGAuA>RYe&`QK7iHAPr*|M%20X=?+WN;KR3y3 zazaj-{Afg@a9qxd6igr`Q3>OiWH$1FEK*Bg!v}{~pZw(T5>SC(QKsLMC?YWfmA=n) zC3IqIo4>ck>I<-;*X^cjl6Yg7FZemYk!V3t%`>uY3u!wh^>e+>HE~SXO;?3|0AwTJ z7xG3N(;H3~vGVV5gOqOCN3n|?GXx1mEP~#zZLWEWCNw7IUa?yI>@Z}h*bxfkOi7h- z)A87}3_rtk9Aa7|qrr%2^RR&WNj8e2@IKN~x<{;DXxipv-O&%LMdy8<7hROaigWTo zh`ToW^ezaqR5w>x#(XXA`5n!n8_%LlG+)f4E+=^+`Bc7@mQts6<0XUpZE$2+2z$N% z(Y0437tpKwJFy=*$9K*2men%1NJkd{Z=L1@J5B>M3-c5eHWAz>x9pydvs}Si^9F1E zuJ-!Yiv(v4wH|d5G6Z-m$fgea3t*@@muBQ$C< {yQ$3ouM9{09ab!Q`c3;=Kuo*ATi4z3& znB6PL!BSsfc&LajRl4G}MgEDp+u)Ht_gcz9ww0`bR|&1H1=2h%xhW&f*&Hy!7=x(a zd6?T}R rBRJ)BL2r1510|2qJ`N-m=j)|X|eG 0!f=M+Fd5DnjfSSKpSoo(@#V>|fR?QJbaomh zf$U8T!a!Un
cl+GC3a(&F;vB3Y`2XMx!Rxh zo!F-cw?Uuva#o|~U7I355@n2n0^An!sCwnm3B(e0{MF{9mI9QrsyXOM8ZLx_pdezK z=b{yDOxDTPVN%}BNZ6kptC&q#Pd$7MxW%KIfrO|8iUURci~6U%&hCPnl+gJ}Cd~Dr zI95ol3rV|{C;BGGZw%GAd+~}ASQE@tCXwWXzsQ#hlo+;KAWYtx@@_LOyW>udbJ(8Y zHfFU+^*hR<1%Kt{3c#>AJ#QdsE&_;SXqa2dJ ~=VS8kHV9z|lV zG&HXwBYvR@TNFTuR R^oT-4QimI+x7xnV0IPi zVW27`5E~3oMFKC RN7!vHUgMA-og%gKU~(RzvR8ou{KaSMAq2 zcvyHCnQm)t?k4@YM8dRWM D- 2rYNGcB@Eiseo%CB;V&HZIJUrD|yV;A!~IEH$tg|1A`H 0<`A#K 1R?0aC~!Q^M 48B9wo+^z;I8no;PVD;f{NRsAaMLZpYtFwd1FIzj=k6gq+(BzSy3bLhvNSL znU<_*{-)W8Y&kwh?Fpu(EcWWSuY%5?yMl3`?*+F4oWeX{v?x$bn-BRQny$`)^^&>$ z6QS<7U{_2SVPt$ 7kN*I0i2GD( zOdLL7HZNW-xg+tWuY3OhaF<+Zz9m2PEv|WZfIIk=msN<}^sFI$ppEzf WPxHk^=DK5>kc3*P`ko9d-0DDW|X@r8!4k4|Z zA*-I!m>7UHo*H2nt4vE*pckn64wW#m-zp8bo4Ov-fL89p=@xVNfQ`VU4gep?%rCfs z50Z8lZ%DJ575Jxv&r1IQAGAMAzY~;o96!=Q%AYdI#j}{bE9 6yibyH!sZ*5Uf>SL327z z;=8~@@Wo9M0u_ukiflK`Ba0JCaM<@72xa153|7?=`du*Bfx`|hUF2saRO)BRe$bM_ zQ(~gi@@`o$kBkY$U^zG9AOW$+ns59u;Y{w4_=m0_&6)=?;54{~>X~A*m*q7SS|*UF zXVl!V9Xxu4Mdw~31qD=4dANzSYgcLmnh8)#r%k$)`DKAp&jhfBSWx^%f? *T3rEG*n5}F|@qzTfcG4B(~VUr}$pwth?G~gj`_7to4%? zYbRvNBXU$T)owcl$$>$SDc>cOEe}>e=alXR4f*jY3BDD?83YBlfULJFMbH+bA{3Mb z%Y?x#+*t&Ue3pugF##5s1yxyH1u_@Fn+k9S9ceOPB4 b1CbY9KA^!keojC&3Rm0>g%WqhvvxtIj z>pA}bCe`h62vp^}(||_vr~|`CZ6g+dal?kWkb1?dp8=N^2O$`>eMOZ*y$$o`u(n5p zs-+|}i@TPWlXZE$P_#CjHfJwUse#~rr9vp}IezyVbzz7*7|_(pH%C{^cNy0}o&`UM z-{{5DX Y8x zWg!fzfS&-d1l8_6yu34+j;px*`U6en=mNu(ZU9(vU>Q-}h>tSMm5LEw5J9J_kKl1p zsd`yPlxT;FSt~sWIuuN+U}DE$p4&pJkl?uu-R|! aEbq;Yl!!3e5OpjiDQ3Dz9^&OT+(XW92m7JWZiWypCm1lHal*a-4l?iaQd zmw9aq>W7c`jZXo%vmPN1>ZQN#30ZwaX+T9GF2G(CTw@KER@O${pu+(!DXW#}Kw1^e zZaQwBuu6ifnfPWBO4<5@SV7Q$s~|C17ntGjZY`{UVFWFV(dGpi#0n^PLUQgjnnD4@ z=8e0E&@&Z6fbDb~>6@_I2KsHU5Q8JC*0PsSq&`y|y*Fc#tjak~Wn?SwEUBdHdsM=| zsEE?1vXf5eyU19SCFve8f*QHO%0eyy0;d1~27?Fuk8^+3qNB|y8N7a?kC10(Y;G5x(rlW5|^Xp;xNwFO>=m4joMxfmmlpIvC;* zTH%39z}JQ+TkBQ$8cAcwz^@|VJ8luTFN^*z8}wLqsJ~!|J8x_M0DB1qJ8_ZKe fyaq@T@KlDu}QEF&3XIl8-i!66B&NAQJDEqcLjG zRpu7Cptw$~HCxpUcpOZPQNg}U^fw#U&Ok9M$iH9NUh!3Q1^F!t9h&Y@#&@0|9FO&J z3qzLvVJ0T{EhkuO@WbCqYLQWnHEY2dcl59+0Z vgc|g #2UqnDau zHVI6pTsLj_jWrQ9Lm{+M-ISw@$B?!2`y|EoS~HjGFzTKh%sJn1361r{#eg?